diff --git a/luaext/lposix.c b/luaext/lposix.c index 0a7c26c71a..2a29d3ed16 100644 --- a/luaext/lposix.c +++ b/luaext/lposix.c @@ -330,26 +330,58 @@ static int Pmkfifo(lua_State *L) /** mkfifo(path) */ } +static void set_cloexec(int fd) +{ + int flags = fcntl(fd, F_GETFD); + + if (flags == -1 || (flags & FD_CLOEXEC)) + return; + + fcntl(fd, F_SETFD, flags | FD_CLOEXEC); +} + +static void set_cloexec_all(void) +{ + const int min_fd = 3; // don't touch stdin/out/err + int fd, open_max; + + open_max = sysconf(_SC_OPEN_MAX); + if (open_max == -1) { + open_max = 1024; + } + + // iterate over fds obtained from /proc + DIR *dir = opendir("/proc/self/fd"); + if (dir == NULL) { + goto fallback; + } + + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + fd = atoi(entry->d_name); + if (fd >= min_fd) + set_cloexec(fd); + } + closedir(dir); + + return; + +fallback: + // iterate over all possible fds + for (fd = min_fd; fd < open_max; fd++) + set_cloexec(fd); +} + static int Pexec(lua_State *L) /** exec(path,[args]) */ { const char *path = luaL_checkstring(L, 1); int i,n=lua_gettop(L); char **argv; - int flag, fdno, open_max; if (!have_forked) return luaL_error(L, "exec not permitted in this context"); - open_max = sysconf(_SC_OPEN_MAX); - if (open_max == -1) { - open_max = 1024; - } - for (fdno = 3; fdno < open_max; fdno++) { - flag = fcntl(fdno, F_GETFD); - if (flag == -1 || (flag & FD_CLOEXEC)) - continue; - fcntl(fdno, F_SETFD, FD_CLOEXEC); - } + set_cloexec_all(); argv = malloc((n+1)*sizeof(char*)); if (argv==NULL) return luaL_error(L,"not enough memory");