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