Use different method to workaround "restorecon_recursive /data"
* Inject entries for MultiROM folders into /file_contexts instead of editing *.rc files. * Thanks nkk71 for the suggestion.
This commit is contained in:
11
multirom.c
11
multirom.c
@@ -975,9 +975,7 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to
|
|||||||
{
|
{
|
||||||
case ROM_DEFAULT:
|
case ROM_DEFAULT:
|
||||||
{
|
{
|
||||||
mount("/realdata", "/data", "", MS_BIND, "");
|
rom_quirks_on_initrd_finalized();
|
||||||
rom_quirks_on_android_mounted_fs(to_boot);
|
|
||||||
umount("/data");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ROM_LINUX_INTERNAL:
|
case ROM_LINUX_INTERNAL:
|
||||||
@@ -997,7 +995,7 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to
|
|||||||
if(multirom_create_media_link() == -1)
|
if(multirom_create_media_link() == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rom_quirks_on_android_mounted_fs(to_boot);
|
rom_quirks_on_initrd_finalized();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(to_boot->partition)
|
if(to_boot->partition)
|
||||||
@@ -2321,9 +2319,10 @@ next_itr:
|
|||||||
int multirom_mount_usb(struct usb_partition *part)
|
int multirom_mount_usb(struct usb_partition *part)
|
||||||
{
|
{
|
||||||
mkdir("/mnt", 0777);
|
mkdir("/mnt", 0777);
|
||||||
|
mkdir("/mnt/mrom", 0777);
|
||||||
|
|
||||||
char path[256];
|
char path[256];
|
||||||
sprintf(path, "/mnt/%s", part->name);
|
snprintf(path, sizeof(path), "/mnt/mrom/%s", part->name);
|
||||||
if(mkdir(path, 0777) != 0 && errno != EEXIST)
|
if(mkdir(path, 0777) != 0 && errno != EEXIST)
|
||||||
{
|
{
|
||||||
ERROR("Failed to create dir for mount %s\n", path);
|
ERROR("Failed to create dir for mount %s\n", path);
|
||||||
@@ -2331,7 +2330,7 @@ int multirom_mount_usb(struct usb_partition *part)
|
|||||||
}
|
}
|
||||||
|
|
||||||
char src[256];
|
char src[256];
|
||||||
sprintf(src, "/dev/block/%s", part->name);
|
snprintf(src, sizeof(src), "/dev/block/%s", part->name);
|
||||||
|
|
||||||
if(strncmp(part->fs, "ntfs", 4) == 0)
|
if(strncmp(part->fs, "ntfs", 4) == 0)
|
||||||
{
|
{
|
||||||
|
|||||||
195
rom_quirks.c
195
rom_quirks.c
@@ -22,141 +22,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/xattr.h>
|
|
||||||
|
|
||||||
#include "multirom.h"
|
|
||||||
#include "rom_quirks.h"
|
#include "rom_quirks.h"
|
||||||
#include "lib/log.h"
|
#include "lib/log.h"
|
||||||
#include "lib/util.h"
|
#include "lib/util.h"
|
||||||
|
|
||||||
#define MULTIROM_DIR_ANDROID "/data/media/0/multirom"
|
|
||||||
#define MULTIROM_DIR_ANDROID_LEN 22
|
|
||||||
#define RESTORECON_LAST "security.restorecon_last"
|
|
||||||
#define RESTORECON_LAST_HACK_PATH "/data/media"
|
|
||||||
#define RESTORECON_LAST_HACK_PATH_LEN 11
|
|
||||||
|
|
||||||
static void write_changed_restorecons(const char *path, FILE *rc)
|
|
||||||
{
|
|
||||||
struct dirent *dt;
|
|
||||||
char *next_path = 0;
|
|
||||||
size_t new_len, allocd = 0;
|
|
||||||
const int path_len = strlen(path);
|
|
||||||
DIR *d = opendir(path);
|
|
||||||
if(!d)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while((dt = readdir(d)))
|
|
||||||
{
|
|
||||||
if(strcmp(dt->d_name, ".") == 0 || strcmp(dt->d_name, "..") == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(dt->d_type == DT_DIR)
|
|
||||||
{
|
|
||||||
new_len = imax((size_t)(path_len + strlen(dt->d_name) + 2), allocd);
|
|
||||||
if(new_len > allocd)
|
|
||||||
{
|
|
||||||
next_path = realloc(next_path, new_len);
|
|
||||||
allocd = new_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
snprintf(next_path, allocd, "%s/%s", path, dt->d_name);
|
|
||||||
const int next_path_len = strlen(next_path);
|
|
||||||
|
|
||||||
if(strncmp(next_path, MULTIROM_DIR_ANDROID, next_path_len) == 0)
|
|
||||||
{
|
|
||||||
if(next_path_len != MULTIROM_DIR_ANDROID_LEN)
|
|
||||||
{
|
|
||||||
fprintf(rc, " restorecon \"%s/%s\"\n", path, dt->d_name);
|
|
||||||
write_changed_restorecons(next_path, rc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
fprintf(rc, " restorecon_recursive \"%s/%s\"\n", path, dt->d_name);
|
|
||||||
|
|
||||||
// restorecon_recursive works only if RESTORECON_LAST xattr contains hash
|
|
||||||
// different from current file_contexts. Because /data/media/ is shared
|
|
||||||
// among multiple ROMs, this doesn't work well because some ROMs don't
|
|
||||||
// set this xattr, so restorecon thinks nothing changed but it did.
|
|
||||||
if (strncmp(next_path, RESTORECON_LAST_HACK_PATH, RESTORECON_LAST_HACK_PATH_LEN) == 0 &&
|
|
||||||
(next_path[RESTORECON_LAST_HACK_PATH_LEN] == 0 || next_path[RESTORECON_LAST_HACK_PATH_LEN] == '/'))
|
|
||||||
{
|
|
||||||
removexattr(next_path, RESTORECON_LAST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fprintf(rc, " restorecon \"%s/%s\"\n", path, dt->d_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir(d);
|
|
||||||
free(next_path);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workaround_rc_restorecon(const char *rc_file_name)
|
|
||||||
{
|
|
||||||
FILE *f_in, *f_out;
|
|
||||||
char *name_out = NULL;
|
|
||||||
char line[512];
|
|
||||||
char *r;
|
|
||||||
int changed = 0;
|
|
||||||
|
|
||||||
f_in = fopen(rc_file_name, "re");
|
|
||||||
if(!f_in)
|
|
||||||
{
|
|
||||||
ERROR("Failed to open input file %s\n", rc_file_name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
name_out = malloc(strlen(rc_file_name)+5);
|
|
||||||
snprintf(name_out, strlen(rc_file_name)+5, "%s.new", rc_file_name);
|
|
||||||
|
|
||||||
f_out = fopen(name_out, "we");
|
|
||||||
if(!f_out)
|
|
||||||
{
|
|
||||||
ERROR("Failed to open output file %s\n", name_out);
|
|
||||||
fclose(f_in);
|
|
||||||
free(name_out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(fgets(line, sizeof(line), f_in))
|
|
||||||
{
|
|
||||||
r = strstr(line, "restorecon_recursive");
|
|
||||||
if(r)
|
|
||||||
{
|
|
||||||
r += strlen("restorecon_recursive");
|
|
||||||
|
|
||||||
while(*r && isspace(*r))
|
|
||||||
++r;
|
|
||||||
|
|
||||||
if(strcmp(r, "/data\n") == 0)
|
|
||||||
{
|
|
||||||
changed = 1;
|
|
||||||
fputc('#', f_out);
|
|
||||||
fputs(line, f_out);
|
|
||||||
write_changed_restorecons("/data", f_out);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fputs(line, f_out);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fputs(line, f_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f_out);
|
|
||||||
fclose(f_in);
|
|
||||||
|
|
||||||
if(changed)
|
|
||||||
{
|
|
||||||
rename(name_out, rc_file_name);
|
|
||||||
chmod(rc_file_name, 0750);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
unlink(name_out);
|
|
||||||
free(name_out);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void workaround_mount_in_sh(const char *path)
|
static void workaround_mount_in_sh(const char *path)
|
||||||
{
|
{
|
||||||
char line[512];
|
char line[512];
|
||||||
@@ -191,21 +61,51 @@ static void workaround_mount_in_sh(const char *path)
|
|||||||
free(tmp_name);
|
free(tmp_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rom_quirks_on_android_mounted_fs(struct multirom_rom *rom)
|
static void inject_file_contexts(void)
|
||||||
{
|
{
|
||||||
// CyanogenMod has init script 50selinuxrelabel which calls
|
FILE *f;
|
||||||
// restorecon on /data. On secondary ROMs, /system is placed
|
char line[512];
|
||||||
// inside /data/media/ and mount-binded to /system, so restorecon
|
|
||||||
// sets contexts to files in /system as if they were in /data.
|
f = fopen("/file_contexts", "re");
|
||||||
// This behaviour is there mainly because of old recoveries which
|
if(!f)
|
||||||
// didn't set contexts properly, so it should be safe to remove
|
|
||||||
// that file entirely.
|
|
||||||
if(rom->type != ROM_ANDROID_USB_IMG && access("/system/etc/init.d/50selinuxrelabel", F_OK) >= 0)
|
|
||||||
{
|
{
|
||||||
INFO("Removing /system/etc/init.d/50selinuxrelabel.\n");
|
ERROR("Failed to open /file_contexts!");
|
||||||
remove("/system/etc/init.d/50selinuxrelabel");
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(fgets(line, sizeof(line), f))
|
||||||
|
{
|
||||||
|
if(strstartswith(line, "/data/media/multirom"))
|
||||||
|
{
|
||||||
|
INFO("/file_contexts has been already injected.");
|
||||||
|
fclose(f);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
INFO("Injecting /file_contexts");
|
||||||
|
f = fopen("/file_contexts", "ae");
|
||||||
|
if(!f)
|
||||||
|
{
|
||||||
|
ERROR("Failed to open /file_contexts for appending!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs("\n"
|
||||||
|
"# MultiROM folders\n"
|
||||||
|
"/data/media/multirom(/.*)? <<none>>\n"
|
||||||
|
"/data/media/0/multirom(/.*)? <<none>>\n"
|
||||||
|
"/realdata/media/multirom(/.*)? <<none>>\n"
|
||||||
|
"/realdata/media/0/multirom(/.*)? <<none>>\n"
|
||||||
|
"/mnt/mrom(/.*)? <<none>>\n",
|
||||||
|
f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rom_quirks_on_initrd_finalized(void)
|
||||||
|
{
|
||||||
// walk over all _regular_ files in /
|
// walk over all _regular_ files in /
|
||||||
DIR *d = opendir("/");
|
DIR *d = opendir("/");
|
||||||
if(d)
|
if(d)
|
||||||
@@ -217,20 +117,19 @@ void rom_quirks_on_android_mounted_fs(struct multirom_rom *rom)
|
|||||||
if(dt->d_type != DT_REG)
|
if(dt->d_type != DT_REG)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// The Android L preview (and presumably later releases) have SELinux
|
// The Android L and later releases have SELinux
|
||||||
// set to "enforcing" and "restorecon_recursive /data" line in init.rc.
|
// set to "enforcing" and "restorecon_recursive /data" line in init.rc.
|
||||||
// Restorecon on /data goes into /data/media/0/multirom/roms/ and changes
|
// Restorecon on /data goes into /data/media/0/multirom/roms/ and changes
|
||||||
// context of all secondary ROMs files to that of /data, including the files
|
// context of all secondary ROMs files to that of /data, including the files
|
||||||
// in secondary ROMs /system dirs. We need to prevent that.
|
// in secondary ROMs /system dirs. We need to prevent that.
|
||||||
if(strstr(dt->d_name, ".rc"))
|
// Right now, we do that by adding entries into /file_contexts that say
|
||||||
{
|
// MultiROM folders don't have any context
|
||||||
snprintf(buff, sizeof(buff), "/%s", dt->d_name);
|
if(strcmp(dt->d_name, "file_contexts") == 0)
|
||||||
workaround_rc_restorecon(buff);
|
inject_file_contexts();
|
||||||
}
|
|
||||||
|
|
||||||
// franco.Kernel includes script init.fk.sh which remounts /system as read only
|
// franco.Kernel includes script init.fk.sh which remounts /system as read only
|
||||||
// comment out lines with mount and /system in all .sh scripts in /
|
// comment out lines with mount and /system in all .sh scripts in /
|
||||||
if(strendswith(dt->d_name, ".sh") && (M(rom->type) & MASK_ANDROID) && rom->type != ROM_ANDROID_USB_IMG)
|
if(strendswith(dt->d_name, ".sh"))
|
||||||
{
|
{
|
||||||
snprintf(buff, sizeof(buff), "/%s", dt->d_name);
|
snprintf(buff, sizeof(buff), "/%s", dt->d_name);
|
||||||
workaround_mount_in_sh(buff);
|
workaround_mount_in_sh(buff);
|
||||||
|
|||||||
@@ -19,6 +19,6 @@
|
|||||||
|
|
||||||
struct multirom_rom;
|
struct multirom_rom;
|
||||||
|
|
||||||
void rom_quirks_on_android_mounted_fs(struct multirom_rom *rom);
|
void rom_quirks_on_initrd_finalized(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user