mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 19:41:10 +00:00
fix(native): a spawn whose dup2 source close-from closed fails with EBADF
This commit is contained in:
1 parent
436e99e02b
commit
107cefbf46
2 files changed
+25
-6
No files matched your search
@@ -878,13 +878,16 @@ static int ddnatv_posix_spawn(pid_t *pid, const char *path,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void apply_closefrom(posix_spawn_file_actions_t *actions);
|
||||
static int apply_closefrom(posix_spawn_file_actions_t *actions);
|
||||
|
||||
int posix_spawn(pid_t *pid, const char *path,
|
||||
const posix_spawn_file_actions_t *file_actions,
|
||||
const posix_spawnattr_t *attrp,
|
||||
char *const argv[], char *const envp[]) {
|
||||
if (file_actions) apply_closefrom((posix_spawn_file_actions_t *)file_actions);
|
||||
if (file_actions) {
|
||||
int bad = apply_closefrom((posix_spawn_file_actions_t *)file_actions);
|
||||
if (bad) return bad;
|
||||
}
|
||||
posix_spawnattr_t sanitized;
|
||||
return ddnatv_posix_spawn(pid, path, file_actions, spawn_attr_for_android(attrp, &sanitized), argv, envp, 0);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ static struct closefrom_entry {
|
||||
int nkeep;
|
||||
int keep[CLOSEFROM_KEEP];
|
||||
int closed_to; // the descriptors up to this one are closed by actions already added
|
||||
int bad_source; // a dup2 after close-from duplicates a descriptor it closed: glibc's EBADF
|
||||
} g_closefrom[CLOSEFROM_SLOTS];
|
||||
static pthread_mutex_t g_closefrom_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
@@ -101,7 +102,17 @@ int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *actions, int fd
|
||||
static int (*orig)(posix_spawn_file_actions_t *, int, int) = NULL;
|
||||
if (!orig) orig = (int (*)(posix_spawn_file_actions_t *, int, int))dlsym(RTLD_NEXT, "posix_spawn_file_actions_adddup2");
|
||||
int ret = orig ? orig(actions, fd, newfd) : ENOSYS;
|
||||
if (ret == 0) closefrom_note_target(actions, newfd);
|
||||
if (ret == 0) {
|
||||
pthread_mutex_lock(&g_closefrom_lock);
|
||||
struct closefrom_entry *e = closefrom_entry(actions, 0);
|
||||
if (e && e->from >= 0 && fd >= e->from) {
|
||||
int reopened = 0;
|
||||
for (int k = 0; k < e->nkeep; k++) reopened |= e->keep[k] == fd;
|
||||
if (!reopened) e->bad_source = 1;
|
||||
}
|
||||
pthread_mutex_unlock(&g_closefrom_lock);
|
||||
closefrom_note_target(actions, newfd);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -125,12 +136,16 @@ int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *actions) {
|
||||
return orig ? orig(actions) : ENOSYS;
|
||||
}
|
||||
|
||||
static void apply_closefrom(posix_spawn_file_actions_t *actions) {
|
||||
static int apply_closefrom(posix_spawn_file_actions_t *actions) {
|
||||
pthread_mutex_lock(&g_closefrom_lock);
|
||||
struct closefrom_entry *e = closefrom_entry(actions, 0);
|
||||
if (!e || e->from < 0) {
|
||||
pthread_mutex_unlock(&g_closefrom_lock);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if (e->bad_source) {
|
||||
pthread_mutex_unlock(&g_closefrom_lock);
|
||||
return EBADF;
|
||||
}
|
||||
int highest = e->highest;
|
||||
DIR *dir = opendir("/proc/self/fd");
|
||||
@@ -152,7 +167,8 @@ static void apply_closefrom(posix_spawn_file_actions_t *actions) {
|
||||
e->closed_to = fd;
|
||||
}
|
||||
pthread_mutex_unlock(&g_closefrom_lock);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static void apply_closefrom(posix_spawn_file_actions_t *actions) { (void)actions; }
|
||||
static int apply_closefrom(posix_spawn_file_actions_t *actions) { (void)actions; return 0; }
|
||||
#endif
|
||||
Reference in new issue
Block a user