Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix thread-unsafe setenv() usage
Since moving the tunnel handling into libopenconnect too, we've been
unsafely using setenv() before spawning vpnc-script. We mustn't do that
in a multi-threaded environment.

So store up all the variables in a list, and apply them after fork(). Or
on Windows, build up the environment block to pass to CreateProcess()
manually.

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
  • Loading branch information
David Woodhouse authored and David Woodhouse committed Oct 30, 2014
1 parent 9018487 commit 7b8fd00
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 117 deletions.
37 changes: 0 additions & 37 deletions compat.c
Expand Up @@ -183,43 +183,6 @@ char *openconnect__strndup(const char *s, size_t n)
}
#endif

#ifndef HAVE_SETENV
int openconnect__setenv(const char *name, const char *value, int overwrite)
{
struct oc_text_buf *buf;

if (!value) {
openconnect__unsetenv(name);
return 0;
}

buf = buf_alloc();
buf_append_utf16le(buf, name);
buf_append_utf16le(buf, "=");
buf_append_utf16le(buf, value);
if (buf_error(buf)) {
errno = -buf_free(buf);
return -1;
}

/* Windows putenv() takes a copy of the string */
_wputenv((wchar_t *)buf->data);
buf_free(buf);

return 0;
}
#endif

#ifndef HAVE_UNSETENV
void openconnect__unsetenv(const char *name)
{
char *buf = alloca(strlen(name) + 2);

sprintf(buf, "%s=", name);
putenv(buf);
}
#endif

#ifndef HAVE_INET_ATON
int openconnect__inet_aton(const char *cp, struct in_addr *addr)
{
Expand Down
2 changes: 0 additions & 2 deletions configure.ac
Expand Up @@ -177,8 +177,6 @@ fi

AC_CHECK_FUNC(__android_log_vprint, [], AC_CHECK_LIB(log, __android_log_vprint, [], []))

AC_CHECK_FUNCS(setenv unsetenv)

AC_ENABLE_SHARED
AC_DISABLE_STATIC

Expand Down
5 changes: 3 additions & 2 deletions library.c
Expand Up @@ -178,6 +178,7 @@ void openconnect_vpninfo_free(struct openconnect_info *vpninfo)
CloseHandle(vpninfo->dtls_event);
#endif
free(vpninfo->peer_addr);
free_optlist(vpninfo->script_env);
free_optlist(vpninfo->cookies);
free_optlist(vpninfo->cstp_options);
free_optlist(vpninfo->dtls_options);
Expand Down Expand Up @@ -657,15 +658,15 @@ int openconnect_setup_tun_device(struct openconnect_info *vpninfo,
STRDUP(vpninfo->vpnc_script, vpnc_script);
STRDUP(vpninfo->ifname, ifname);

set_script_env(vpninfo);
prepare_script_env(vpninfo);
script_config_tun(vpninfo, "pre-init");

tun_fd = os_setup_tun(vpninfo);
if (tun_fd < 0)
return tun_fd;

legacy_ifname = openconnect_utf8_to_legacy(vpninfo, vpninfo->ifname);
setenv("TUNDEV", legacy_ifname, 1);
script_setenv(vpninfo, "TUNDEV", legacy_ifname, 0);
if (legacy_ifname != vpninfo->ifname)
free(legacy_ifname);
script_config_tun(vpninfo, "connect");
Expand Down
16 changes: 6 additions & 10 deletions openconnect-internal.h
Expand Up @@ -289,6 +289,8 @@ struct openconnect_info {
struct oc_vpn_option *cstp_options;
struct oc_vpn_option *dtls_options;

struct oc_vpn_option *script_env;

unsigned pfs;
#if defined(OPENCONNECT_OPENSSL)
X509 *cert_x509;
Expand Down Expand Up @@ -493,14 +495,6 @@ char *openconnect__strcasestr(const char *haystack, const char *needle);
#define strndup openconnect__strndup
char *openconnect__strndup(const char *s, size_t n);
#endif
#ifndef HAVE_SETENV
#define setenv openconnect__setenv
int openconnect__setenv(const char *name, const char *value, int overwrite);
#endif
#ifndef HAVE_UNSETENV
#define unsetenv openconnect__unsetenv
void openconnect__unsetenv(const char *name);
#endif

#ifndef HAVE_INET_ATON
#define inet_aton openconnect__inet_aton
Expand Down Expand Up @@ -568,9 +562,11 @@ char *openconnect_legacy_to_utf8(struct openconnect_info *vpninfo, const char *l
#endif

/* script.c */
int setenv_int(const char *opt, int value);
void set_script_env(struct openconnect_info *vpninfo);
int script_setenv(struct openconnect_info *vpninfo, const char *opt, const char *val, int append);
int script_setenv_int(struct openconnect_info *vpninfo, const char *opt, int value);
void prepare_script_env(struct openconnect_info *vpninfo);
int script_config_tun(struct openconnect_info *vpninfo, const char *reason);
int apply_script_env(struct openconnect_info *vpninfo);

/* tun.c / tun-win32.c */
void os_shutdown_tun(struct openconnect_info *vpninfo);
Expand Down

0 comments on commit 7b8fd00

Please sign in to comment.