All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: Anthony Liguori <aliguori@amazon.com>,
	Markus Armbruster <armbru@redhat.com>,
	"Dr. David Alan Gilbert" <dgilbert@redhat.com>,
	Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 07/10] vnc: track & limit connections
Date: Mon, 12 Jan 2015 13:53:54 +0100	[thread overview]
Message-ID: <1421067237-6955-8-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1421067237-6955-1-git-send-email-kraxel@redhat.com>

Also track the number of connections in "connecting" and "shared" state
(in addition to the "exclusive" state).  Apply a configurable limit to
these connections.

The logic to apply the limit to connections in "shared" state is pretty
simple:  When the limit is reached no new connections are allowed.

The logic to apply the limit to connections in "connecting" state (this
is the state you are in *before* successful authentication) is
slightly different:  A new connect kicks out the oldest client which is
still in "connecting" state.  This avoids a easy DoS by unauthenticated
users by simply opening connections until the limit is reached.

Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 ui/vnc.c | 46 +++++++++++++++++++++++++++++++++++++++++++---
 ui/vnc.h |  3 +++
 2 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index dd09fc1..2ed16dc 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -68,12 +68,34 @@ static void vnc_set_share_mode(VncState *vs, VncShareMode mode)
             vs->csock, mn[vs->share_mode], mn[mode]);
 #endif
 
-    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
+    switch (vs->share_mode) {
+    case VNC_SHARE_MODE_CONNECTING:
+        vs->vd->num_connecting--;
+        break;
+    case VNC_SHARE_MODE_SHARED:
+        vs->vd->num_shared--;
+        break;
+    case VNC_SHARE_MODE_EXCLUSIVE:
         vs->vd->num_exclusive--;
+        break;
+    default:
+        break;
     }
+
     vs->share_mode = mode;
-    if (vs->share_mode == VNC_SHARE_MODE_EXCLUSIVE) {
+
+    switch (vs->share_mode) {
+    case VNC_SHARE_MODE_CONNECTING:
+        vs->vd->num_connecting++;
+        break;
+    case VNC_SHARE_MODE_SHARED:
+        vs->vd->num_shared++;
+        break;
+    case VNC_SHARE_MODE_EXCLUSIVE:
         vs->vd->num_exclusive++;
+        break;
+    default:
+        break;
     }
 }
 
@@ -2337,6 +2359,11 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
     }
     vnc_set_share_mode(vs, mode);
 
+    if (vs->vd->num_shared > vs->vd->connections_limit) {
+        vnc_disconnect_start(vs);
+        return 0;
+    }
+
     vs->client_width = pixman_image_get_width(vs->vd->server);
     vs->client_height = pixman_image_get_height(vs->vd->server);
     vnc_write_u16(vs, vs->client_width);
@@ -2889,6 +2916,15 @@ static void vnc_connect(VncDisplay *vd, int csock,
     {
         vnc_init_state(vs);
     }
+
+    if (vd->num_connecting > vd->connections_limit) {
+        QTAILQ_FOREACH(vs, &vd->clients, next) {
+            if (vs->share_mode == VNC_SHARE_MODE_CONNECTING) {
+                vnc_disconnect_start(vs);
+                return;
+            }
+        }
+    }
 }
 
 void vnc_init_state(VncState *vs)
@@ -2907,7 +2943,7 @@ void vnc_init_state(VncState *vs)
     qemu_mutex_init(&vs->output_mutex);
     vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
 
-    QTAILQ_INSERT_HEAD(&vd->clients, vs, next);
+    QTAILQ_INSERT_TAIL(&vd->clients, vs, next);
 
     graphic_hw_update(vd->dcl.con);
 
@@ -3097,6 +3133,9 @@ static QemuOptsList qemu_vnc_opts = {
             .name = "head",
             .type = QEMU_OPT_NUMBER,
         },{
+            .name = "connections",
+            .type = QEMU_OPT_NUMBER,
+        },{
             .name = "password",
             .type = QEMU_OPT_BOOL,
         },{
@@ -3210,6 +3249,7 @@ void vnc_display_open(const char *id, Error **errp)
     } else {
         vs->share_policy = VNC_SHARE_POLICY_ALLOW_EXCLUSIVE;
     }
+    vs->connections_limit = qemu_opt_get_number(opts, "connections", 32);
 
  #ifdef CONFIG_VNC_WS
     websocket = qemu_opt_get(opts, "websocket");
diff --git a/ui/vnc.h b/ui/vnc.h
index 6fe8278..5e2b1a5 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -150,7 +150,10 @@ typedef enum VncSharePolicy {
 struct VncDisplay
 {
     QTAILQ_HEAD(, VncState) clients;
+    int num_connecting;
+    int num_shared;
     int num_exclusive;
+    int connections_limit;
     VncSharePolicy share_policy;
     int lsock;
 #ifdef CONFIG_VNC_WS
-- 
1.8.3.1

  parent reply	other threads:[~2015-01-12 12:54 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-12 12:53 [Qemu-devel] [PATCH 00/10] vnc: add support for multiple vnc displays Gerd Hoffmann
2015-01-12 12:53 ` [Qemu-devel] [PATCH 01/10] vnc: remove vnc_display global Gerd Hoffmann
2015-01-12 12:53 ` [Qemu-devel] [PATCH 02/10] vnc: remove unused DisplayState parameter, add id instead Gerd Hoffmann
2015-01-12 12:53 ` [Qemu-devel] [PATCH 03/10] vnc: add display id to acl names Gerd Hoffmann
2015-01-12 12:53 ` [Qemu-devel] [PATCH 04/10] vnc: switch to QemuOpts, allow multiple servers Gerd Hoffmann
2015-02-13 18:25   ` Markus Armbruster
2015-02-17  8:50     ` Gerd Hoffmann
2015-02-17  8:58     ` Gerd Hoffmann
2015-02-17 12:15       ` Markus Armbruster
2015-02-13 18:30   ` Markus Armbruster
2015-01-12 12:53 ` [Qemu-devel] [PATCH 05/10] vnc: allow binding servers to qemu consoles Gerd Hoffmann
2015-01-12 12:53 ` [Qemu-devel] [PATCH 06/10] vnc: update docs/multiseat.txt Gerd Hoffmann
2015-01-12 12:53 ` Gerd Hoffmann [this message]
2015-01-12 12:53 ` [Qemu-devel] [PATCH 08/10] vnc: factor out qmp_query_client_list Gerd Hoffmann
2015-01-12 12:53 ` [Qemu-devel] [PATCH 09/10] monitor: add query-vnc-servers command Gerd Hoffmann
2015-02-13 19:44   ` Eric Blake
2015-01-12 12:53 ` [Qemu-devel] [PATCH 10/10] monitor: add vnc websockets Gerd Hoffmann
2015-02-13 19:45   ` Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1421067237-6955-8-git-send-email-kraxel@redhat.com \
    --to=kraxel@redhat.com \
    --cc=aliguori@amazon.com \
    --cc=armbru@redhat.com \
    --cc=dgilbert@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.