]> prime8.dev >> repos - ttyd.git/commitdiff
protocol: fix potential pty buf leak
authorShuanglei Tao <tsl0922@gmail.com>
Thu, 18 Aug 2022 02:35:23 +0000 (10:35 +0800)
committerShuanglei Tao <tsl0922@gmail.com>
Thu, 18 Aug 2022 02:38:55 +0000 (10:38 +0800)
src/protocol.c
src/pty.c
src/pty.h
src/server.h

index 7562d59606c7c9c3e601645a82f0057df25e3c49..731b54fa5ed803a19f016f53260cd07149788523 100644 (file)
@@ -69,29 +69,43 @@ static bool check_host_origin(struct lws *wsi) {
   return len > 0 && strcasecmp(buf, host_buf) == 0;
 }
 
+static pty_ctx_t *pty_ctx_init(struct pss_tty *pss) {
+  pty_ctx_t *ctx = xmalloc(sizeof(pty_ctx_t));
+  ctx->pss = pss;
+  ctx->ws_closed = false;
+  return ctx;
+}
+
+static void pty_ctx_free(pty_ctx_t *ctx) { free(ctx); }
+
 static void process_read_cb(pty_process *process, pty_buf_t *buf, bool eof) {
-  if (process->killed) return ;
+  pty_ctx_t *ctx = (pty_ctx_t *)process->ctx;
+  if (ctx->ws_closed) {
+    pty_buf_free(buf);
+    return;
+  }
 
-  struct pss_tty *pss = (struct pss_tty *)process->ctx;
-  if (eof && !process_running(pss->process))
-    pss->lws_close_status = pss->process->exit_code == 0 ? 1000 : 1006;
+  if (eof && !process_running(process))
+    ctx->pss->lws_close_status = process->exit_code == 0 ? 1000 : 1006;
   else
-    pss->pty_buf = buf;
-
-  lws_callback_on_writable(pss->wsi);
+    ctx->pss->pty_buf = buf;
+  lws_callback_on_writable(ctx->pss->wsi);
 }
 
 static void process_exit_cb(pty_process *process) {
-  if (process->killed) {
+  pty_ctx_t *ctx = (pty_ctx_t *)process->ctx;
+  if (ctx->ws_closed) {
     lwsl_notice("process killed with signal %d, pid: %d\n", process->exit_signal, process->pid);
-    return ;
+    goto done;
   }
 
   lwsl_notice("process exited with code %d, pid: %d\n", process->exit_code, process->pid);
-  struct pss_tty *pss = (struct pss_tty *)process->ctx;
-  pss->process = NULL;
-  pss->lws_close_status = process->exit_code == 0 ? 1000 : 1006;
-  lws_callback_on_writable(pss->wsi);
+  ctx->pss->process = NULL;
+  ctx->pss->lws_close_status = process->exit_code == 0 ? 1000 : 1006;
+  lws_callback_on_writable(ctx->pss->wsi);
+
+done:
+  pty_ctx_free(ctx);
 }
 
 static char **build_args(struct pss_tty *pss) {
@@ -134,7 +148,7 @@ static char **build_env(struct pss_tty *pss) {
 }
 
 static bool spawn_process(struct pss_tty *pss, uint16_t columns, uint16_t rows) {
-  pty_process *process = process_init((void *)pss, server->loop, build_args(pss), build_env(pss));
+  pty_process *process = process_init((void *)pty_ctx_init(pss), server->loop, build_args(pss), build_env(pss));
   if (server->cwd != NULL) process->cwd = strdup(server->cwd);
   if (columns > 0) process->columns = columns;
   if (rows > 0) process->rows = rows;
@@ -356,10 +370,13 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
         free(pss->args[i]);
       }
 
-      if (process_running(pss->process)) {
-        pty_pause(pss->process);
-        lwsl_notice("killing process, pid: %d\n", pss->process->pid);
-        pty_kill(pss->process, server->sig_code);
+      if (pss->process != NULL) {
+        ((pty_ctx_t *)pss->process->ctx)->ws_closed = true;
+        if (process_running(pss->process)) {
+          pty_pause(pss->process);
+          lwsl_notice("killing process, pid: %d\n", pss->process->pid);
+          pty_kill(pss->process, server->sig_code);
+        }
       }
 
       if (server->once && server->client_count == 0) {
index ec06557593baa7f5feb85ea0981442dbfa5e62a1..2fda996be06dc4e16c607fe750516617f4dbd893 100644 (file)
--- a/src/pty.c
+++ b/src/pty.c
@@ -51,7 +51,8 @@ pty_buf_t *pty_buf_init(char *base, size_t len) {
 }
 
 void pty_buf_free(pty_buf_t *buf) {
-  free(buf->base);
+  if (buf == NULL) return;
+  if (buf->base != NULL) free(buf->base);
   free(buf);
 }
 
@@ -105,6 +106,7 @@ void process_free(pty_process *process) {
 #else
   uv_thread_join(&process->tid);
 #endif
+  close(process->pty);
   if (process->in != NULL) uv_close((uv_handle_t *) process->in, close_cb);
   if (process->out != NULL) uv_close((uv_handle_t *) process->out, close_cb);
   if (process->argv != NULL) free(process->argv);
@@ -153,7 +155,6 @@ bool pty_resize(pty_process *process) {
 
 bool pty_kill(pty_process *process, int sig) {
   if (process == NULL) return false;
-  process->killed = true;
 #ifdef _WIN32
   return TerminateProcess(process->handle, 1) != 0;
 #else
index 3efa5587c6a0350b51658c37b0b7297509b9d51e..c3f761c34ab58c0a02198e1f1c435d1a496f6c67 100644 (file)
--- a/src/pty.h
+++ b/src/pty.h
@@ -29,7 +29,6 @@ typedef void (*pty_exit_cb)(pty_process *);
 struct pty_process_ {
   int pid, exit_code, exit_signal;
   uint16_t columns, rows;
-  bool killed;
 #ifdef _WIN32
   STARTUPINFOEXW si;
   HPCON pty;
index b122d1c151acd9c3064cad3cf0aa6dad890aca16..794965af5402d1c813037e80ad696e777e1494f1 100644 (file)
@@ -56,6 +56,11 @@ struct pss_tty {
   int lws_close_status;
 };
 
+typedef struct {
+  struct pss_tty *pss;
+  bool ws_closed;
+} pty_ctx_t ;
+
 struct server {
   int client_count;        // client count
   char *prefs_json;        // client preferences