mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
android: open the core path that passed the folder check
runloop_core_dylib_load resolved the core's path to check that it lies in the app's own folders, then handed the original, unresolved path to dlopen. Any symlink on that path could be repointed between the check and the open. android_core_path_allowed becomes android_core_path_resolve, which hands back the resolved path it checked, and that path is the one opened. Which cores are allowed is unchanged.
This commit is contained in:
1 parent
d94f129883
commit
d7de9cc7b6
3 files changed
+27
-9
No files matched your search
@@ -1558,16 +1558,12 @@ static void android_env_derive_application_info(JNIEnv *env, jobject activity)
|
||||
(*env)->DeleteLocalRef(env, appinfo);
|
||||
}
|
||||
|
||||
bool android_core_path_allowed(const char *path)
|
||||
static bool android_core_real_path_allowed(const char *real_path)
|
||||
{
|
||||
char real_path[PATH_MAX_LENGTH];
|
||||
const char *s;
|
||||
size_t _len;
|
||||
size_t i;
|
||||
|
||||
strlcpy(real_path, path, sizeof(real_path));
|
||||
if (!path_resolve_realpath(real_path, sizeof(real_path), true))
|
||||
*real_path = '\0';
|
||||
for (i = 0; i < ARRAY_SIZE(android_core_dirs); i++)
|
||||
{
|
||||
_len = strlen(android_core_dirs[i]);
|
||||
@@ -1595,6 +1591,20 @@ bool android_core_path_allowed(const char *path)
|
||||
&& strchr(s + _len, '/'));
|
||||
}
|
||||
|
||||
bool android_core_path_resolve(const char *path, char *s, size_t len)
|
||||
{
|
||||
if ( !path || !*path
|
||||
|| strlcpy(s, path, len) >= len
|
||||
|| !path_resolve_realpath(s, len, true)
|
||||
|| !android_core_real_path_allowed(s))
|
||||
{
|
||||
if (len)
|
||||
*s = '\0';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* getPackageManager().getPackageInfo(getPackageName(), 0).versionCode. */
|
||||
static unsigned android_env_derive_version_code(JNIEnv *env, jobject activity)
|
||||
{
|
||||
|
||||
@@ -583,7 +583,10 @@ void frontend_android_get_version(int32_t *major, int32_t *minor, int32_t *rel);
|
||||
|
||||
void frontend_android_get_version_sdk(int32_t *sdk);
|
||||
|
||||
bool android_core_path_allowed(const char *path);
|
||||
/* Resolves @path, symlinks included, into @s; true only when the
|
||||
* result lies in one of the app's own core folders. Open @s, not
|
||||
* @path: the checked path is then the opened one. */
|
||||
bool android_core_path_resolve(const char *path, char *s, size_t len);
|
||||
|
||||
bool is_screen_reader_enabled(void);
|
||||
|
||||
|
||||
@@ -842,8 +842,11 @@ void libretro_get_environment_info(
|
||||
dylib_t runloop_core_dylib_load(const char *path, bool quiet)
|
||||
{
|
||||
#if defined(ANDROID)
|
||||
/* Another app's intent can name the core */
|
||||
if (!android_core_path_allowed(path))
|
||||
/* Another app's intent can name the core. The resolved path that
|
||||
* passed the check is the one opened, so no symlink on the way can
|
||||
* be swapped between the check and the open. */
|
||||
char real_path[PATH_MAX_LENGTH];
|
||||
if (!android_core_path_resolve(path, real_path, sizeof(real_path)))
|
||||
{
|
||||
if (!quiet)
|
||||
RARCH_ERR("[Core] Not loading \"%s\": not found in the app's own folders.\n",
|
||||
@@ -852,8 +855,10 @@ dylib_t runloop_core_dylib_load(const char *path, bool quiet)
|
||||
dylib_error();
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return dylib_load(real_path);
|
||||
#else
|
||||
return dylib_load(path);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Whether the core path is resolved through symlinks before it is
|
||||
|
||||
Reference in new issue
Block a user