chattr -i for log directory (#1398)
Co-authored-by: Howard Wu <40033067+Howard20181@users.noreply.github.com>
This commit is contained in:
parent
6dcceec3c9
commit
a04f2159ad
|
|
@ -31,6 +31,11 @@
|
|||
#include "service.h"
|
||||
#include "symbol_cache.h"
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static_assert(FS_IOC_SETFLAGS == LP_SELECT(0x40046602, 0x40086602));
|
||||
|
||||
namespace lspd {
|
||||
extern int *allowUnload;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import android.os.ParcelFileDescriptor;
|
|||
import android.os.SELinux;
|
||||
import android.os.SharedMemory;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Os;
|
||||
import android.system.OsConstants;
|
||||
import android.util.Log;
|
||||
|
||||
|
|
@ -45,6 +46,8 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import hidden.HiddenApiBridge;
|
||||
|
||||
public class ConfigFileManager {
|
||||
static final Path basePath = Paths.get("/data/adb/lspd");
|
||||
static final Path managerApkPath = basePath.resolve("manager.apk");
|
||||
|
|
@ -144,12 +147,26 @@ public class ConfigFileManager {
|
|||
});
|
||||
}
|
||||
|
||||
public static boolean chattr0(Path path) {
|
||||
try {
|
||||
var dir = Os.open(path.toAbsolutePath().toString(), OsConstants.O_RDONLY, 0);
|
||||
HiddenApiBridge.Os_ioctlInt(dir, HiddenApiBridge.VMRuntime_is64Bit() ? 0x40086602 : 0x40046602, 0);
|
||||
Os.close(dir);
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
Log.d(TAG, "chattr 0", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void moveLogDir() {
|
||||
try {
|
||||
if (Files.exists(logDirPath)) {
|
||||
if (chattr0(logDirPath)) {
|
||||
deleteFolderIfExists(oldLogDirPath);
|
||||
Files.move(logDirPath, oldLogDirPath);
|
||||
}
|
||||
}
|
||||
Files.createDirectories(logDirPath);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import org.lsposed.lspd.BuildConfig;
|
|||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
|
@ -19,7 +20,6 @@ import java.nio.file.Files;
|
|||
import java.nio.file.LinkOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class LogcatService implements Runnable {
|
||||
private static final String TAG = "LSPosedLogcat";
|
||||
|
|
@ -27,8 +27,8 @@ public class LogcatService implements Runnable {
|
|||
ParcelFileDescriptor.MODE_CREATE |
|
||||
ParcelFileDescriptor.MODE_TRUNCATE |
|
||||
ParcelFileDescriptor.MODE_APPEND;
|
||||
private Path modulesLog = null;
|
||||
private Path verboseLog = null;
|
||||
private int modulesFd = -1;
|
||||
private int verboseFd = -1;
|
||||
private Thread thread = null;
|
||||
|
||||
@SuppressLint("UnsafeDynamicallyLoadedCode")
|
||||
|
|
@ -56,42 +56,45 @@ public class LogcatService implements Runnable {
|
|||
try {
|
||||
File log;
|
||||
if (isVerboseLog) {
|
||||
checkFdFile(verboseLog);
|
||||
checkFd(verboseFd);
|
||||
log = ConfigFileManager.getNewVerboseLogPath();
|
||||
} else {
|
||||
checkFdFile(modulesLog);
|
||||
checkFd(modulesFd);
|
||||
log = ConfigFileManager.getNewModulesLogPath();
|
||||
}
|
||||
Log.i(TAG, "New log file: " + log);
|
||||
ConfigFileManager.chattr0(log.toPath().getParent());
|
||||
int fd = ParcelFileDescriptor.open(log, mode).detachFd();
|
||||
var fdFile = Paths.get("/proc/self/fd", String.valueOf(fd));
|
||||
if (isVerboseLog) verboseLog = fdFile;
|
||||
else modulesLog = fdFile;
|
||||
if (isVerboseLog) verboseFd = fd;
|
||||
else modulesFd = fd;
|
||||
return fd;
|
||||
} catch (IOException e) {
|
||||
if (isVerboseLog) verboseLog = null;
|
||||
else modulesLog = null;
|
||||
if (isVerboseLog) verboseFd = -1;
|
||||
else modulesFd = -1;
|
||||
Log.w(TAG, "refreshFd", e);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkFdFile(Path fdFile) {
|
||||
if (fdFile == null) return;
|
||||
private static void checkFd(int fd) {
|
||||
if (fd == -1) return;
|
||||
try {
|
||||
var file = Files.readSymbolicLink(fdFile);
|
||||
if (!Files.exists(file)) {
|
||||
var jfd = new FileDescriptor();
|
||||
jfd.getClass().getDeclaredMethod("setInt$", int.class).invoke(jfd, fd);
|
||||
var stat = Os.fstat(jfd);
|
||||
if (stat.st_nlink == 0) {
|
||||
var file = Files.readSymbolicLink(fdToPath(fd));
|
||||
var parent = file.getParent();
|
||||
if (!Files.isDirectory(parent, LinkOption.NOFOLLOW_LINKS)) {
|
||||
if (ConfigFileManager.chattr0(parent))
|
||||
Files.deleteIfExists(parent);
|
||||
}
|
||||
Files.createDirectories(parent);
|
||||
var name = file.getFileName().toString();
|
||||
var originName = name.substring(0, name.lastIndexOf(' '));
|
||||
Files.copy(fdFile, parent.resolve(originName));
|
||||
Files.copy(file, parent.resolve(originName));
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, "checkFd " + fdFile, e);
|
||||
} catch (Throwable e) {
|
||||
Log.w(TAG, "checkFd " + fd, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +136,7 @@ public class LogcatService implements Runnable {
|
|||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "GetProp: " + e + ": " + Arrays.toString(e.getStackTrace()));
|
||||
Log.e(TAG, "GetProp: ", e);
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
|
|
@ -143,7 +146,7 @@ public class LogcatService implements Runnable {
|
|||
writer.append(sb);
|
||||
}
|
||||
} catch (IOException | InterruptedException | NullPointerException e) {
|
||||
Log.e(TAG, "GetProp: " + Arrays.toString(e.getStackTrace()));
|
||||
Log.e(TAG, "GetProp: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -163,24 +166,25 @@ public class LogcatService implements Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
static private Path fdToPath(int fd) {
|
||||
if (fd == -1) return null;
|
||||
else return Paths.get("/proc/self/fd", String.valueOf(fd));
|
||||
}
|
||||
|
||||
public File getVerboseLog() {
|
||||
return verboseLog.toFile();
|
||||
var path = fdToPath(verboseFd);
|
||||
return path == null ? null : path.toFile();
|
||||
}
|
||||
|
||||
public File getModulesLog() {
|
||||
return modulesLog.toFile();
|
||||
var path = fdToPath(modulesFd);
|
||||
return path == null ? null : path.toFile();
|
||||
}
|
||||
|
||||
public void checkLogFile() {
|
||||
try {
|
||||
modulesLog.toRealPath();
|
||||
} catch (IOException e) {
|
||||
if (modulesFd == -1)
|
||||
refresh(false);
|
||||
}
|
||||
try {
|
||||
verboseLog.toRealPath();
|
||||
} catch (IOException e) {
|
||||
if (verboseFd == -1)
|
||||
refresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,12 +30,20 @@ import android.content.res.CompatibilityInfo;
|
|||
import android.content.res.Resources;
|
||||
import android.content.res.ResourcesImpl;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.UserHandle;
|
||||
import android.system.ErrnoException;
|
||||
import android.system.Int32Ref;
|
||||
import android.system.Os;
|
||||
import android.util.MutableInt;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
|
||||
public class HiddenApiBridge {
|
||||
public static int AssetManager_addAssetPath(AssetManager am, String path) {
|
||||
|
|
@ -91,4 +99,18 @@ public class HiddenApiBridge {
|
|||
public static CompatibilityInfo Resources_getCompatibilityInfo(Resources res) {
|
||||
return res.getCompatibilityInfo();
|
||||
}
|
||||
|
||||
public static int Os_ioctlInt(FileDescriptor fd, int cmd, int arg) throws ErrnoException {
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
|
||||
return Os.ioctlInt(fd, cmd, new MutableInt(arg));
|
||||
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||
return Os.ioctlInt(fd, cmd, new Int32Ref(arg));
|
||||
} else {
|
||||
return Os.ioctlInt(fd, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean VMRuntime_is64Bit() {
|
||||
return VMRuntime.getRuntime().is64Bit();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
package android.os;
|
||||
|
||||
public class Build {
|
||||
public static class VERSION {
|
||||
public final static int SDK_INT = SystemProperties.getInt(
|
||||
"ro.build.version.sdk", 0);
|
||||
}
|
||||
public static class VERSION_CODES {
|
||||
public static final int O_MR1 = 27;
|
||||
public static final int P = 28;
|
||||
public static final int Q = 29;
|
||||
public static final int R = 30;
|
||||
public static final int S = 31;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package android.system;
|
||||
|
||||
public final class ErrnoException extends Exception {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
package android.system;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Int32Ref {
|
||||
public int value;
|
||||
|
||||
public Int32Ref(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return Objects.toString(this);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package android.system;
|
||||
|
||||
import android.util.MutableInt;
|
||||
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
|
||||
public class Os {
|
||||
public static int ioctlInt(FileDescriptor fd, int cmd, MutableInt arg) throws ErrnoException {
|
||||
throw new ErrnoException();
|
||||
}
|
||||
|
||||
@RequiresApi(27)
|
||||
public static int ioctlInt(FileDescriptor fd, int cmd, Int32Ref arg) throws ErrnoException {
|
||||
throw new ErrnoException();
|
||||
}
|
||||
|
||||
@RequiresApi(31)
|
||||
public static int ioctlInt(FileDescriptor fd, int cmd) throws ErrnoException {
|
||||
throw new ErrnoException();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package android.util;
|
||||
|
||||
public final class MutableInt {
|
||||
public int value;
|
||||
|
||||
public MutableInt(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue