|
70 | 70 | import java.util.HashSet; |
71 | 71 | import java.util.List; |
72 | 72 | import java.util.Locale; |
| 73 | +import java.util.stream.Stream; |
73 | 74 | import java.util.zip.Deflater; |
74 | 75 | import java.util.zip.ZipEntry; |
75 | 76 | import java.util.zip.ZipFile; |
@@ -454,20 +455,38 @@ static void ensureModuleFilePath(String path) throws RemoteException { |
454 | 455 |
|
455 | 456 | static Path resolveModuleDir(String packageName, String dir, int userId, int uid) throws IOException { |
456 | 457 | var path = modulePath.resolve(String.valueOf(userId)).resolve(packageName).resolve(dir).normalize(); |
457 | | - if (uid != -1) { |
458 | | - if (path.toFile().mkdirs()) { |
459 | | - try { |
460 | | - SELinux.setFileContext(path.toString(), "u:object_r:xposed_data:s0"); |
461 | | - Os.chown(path.toString(), uid, uid); |
462 | | - Os.chmod(path.toString(), 0755); |
463 | | - } catch (ErrnoException e) { |
464 | | - throw new IOException(e); |
465 | | - } |
| 458 | + // Ensure the directory and any necessary parent directories exist. |
| 459 | + path.toFile().mkdirs(); |
| 460 | + |
| 461 | + if (SELinux.getFileContext(path.toString()) != "u:object_r:xposed_data:s0") { |
| 462 | + // SELinux label could be reset after a reboot. |
| 463 | + try { |
| 464 | + setSelinuxContextRecursive(path, "u:object_r:xposed_data:s0"); |
| 465 | + Os.chown(path.toString(), uid, uid); |
| 466 | + Os.chmod(path.toString(), 0755); |
| 467 | + } catch (ErrnoException e) { |
| 468 | + throw new IOException(e); |
466 | 469 | } |
467 | 470 | } |
468 | 471 | return path; |
469 | 472 | } |
470 | 473 |
|
| 474 | + private static void setSelinuxContextRecursive(Path path, String context) throws IOException { |
| 475 | + try { |
| 476 | + SELinux.setFileContext(path.toString(), context); |
| 477 | + |
| 478 | + if (Files.isDirectory(path)) { |
| 479 | + try (Stream<Path> stream = Files.list(path)) { |
| 480 | + for (Path entry : (Iterable<Path>) stream::iterator) { |
| 481 | + setSelinuxContextRecursive(entry, context); |
| 482 | + } |
| 483 | + } |
| 484 | + } |
| 485 | + } catch (Exception e) { |
| 486 | + throw new IOException("Failed to recursively set SELinux context for " + path, e); |
| 487 | + } |
| 488 | + } |
| 489 | + |
471 | 490 | private static class FileLocker { |
472 | 491 | private final FileChannel lockChannel; |
473 | 492 | private final FileLock locker; |
|
0 commit comments