Multiple vulnerabilities in handle-vpn-block-networks handler of vpnsvc D-Bus service 69/234369/3
authorJeon YoungHo <ykernel.jeon@samsung.com>
Thu, 7 May 2020 13:27:19 +0000 (22:27 +0900)
committerCheoleun Moon <chleun.moon@samsung.com>
Tue, 26 May 2020 03:06:51 +0000 (12:06 +0900)
Change-Id: Iff6033ce86a124f70d9062a6f00928e305763c02
Signed-off-by: Jeon YoungHo <ykernel.jeon@samsung.com>
packaging/net-config.spec
src/vpnsvc.c

index 8402b43..e68037b 100755 (executable)
@@ -1,6 +1,6 @@
 Name:          net-config
 Summary:       TIZEN Network Configuration service
-Version:       1.1.154
+Version:       1.1.155
 Release:       3
 Group:         System/Network
 License:       Apache-2.0
index 8ed0608..04f6ae1 100755 (executable)
@@ -145,6 +145,8 @@ gboolean handle_vpn_down(Vpnsvc *object,
        return TRUE;
 }
 
+#define MAX_NUM_ROUTE_RULE 255
+
 gboolean handle_vpn_block_networks(Vpnsvc *object,
                                                                                        GDBusMethodInvocation *invocation,
                                                                                        GVariant *arg_nets_vpn,
@@ -155,71 +157,100 @@ gboolean handle_vpn_block_networks(Vpnsvc *object,
        DBG("handle_vpn_block_networks");
 
        int result = VPNSVC_ERROR_NONE;
+       if (arg_nr_nets_vpn > MAX_NUM_ROUTE_RULE) {
+               ERR("Number of allowing networks over VPN interface is exceeded %d,"
+                                               " Limit is %d", arg_nr_nets_vpn, MAX_NUM_ROUTE_RULE);
+               result = VPNSVC_ERROR_INVALID_PARAMETER;
+               goto method_complete;
+       }
 
-       char *nets_vpn[arg_nr_nets_vpn];
-       int prefix_vpn[arg_nr_nets_vpn];
-
-       char *nets_orig[arg_nr_nets_vpn];
-       int prefix_orig[arg_nr_nets_vpn];
-
-       int i = 0;
-       GVariantIter iter;
-       gchar* route_dest;
-       gint route_prefix;
-
-       DBG("vpn_block_networks");
-
-       memset(nets_vpn, 0, sizeof(char *) * arg_nr_nets_vpn);
-       memset(prefix_vpn, 0, sizeof(int) * arg_nr_nets_vpn);
-       memset(nets_orig, 0, sizeof(char *) * arg_nr_nets_vpn);
-       memset(prefix_orig, 0, sizeof(int) * arg_nr_nets_vpn);
-
-       /* arg_nets_vpn check */
-       if (arg_nr_nets_vpn > 0) {
-               if (arg_nets_vpn != NULL) {
-                       GVariant *dict_nets_vpn = g_variant_get_variant(arg_nets_vpn);
-                       g_variant_iter_init(&iter, dict_nets_vpn);
-                       i = 0;
-                       while (g_variant_iter_loop(&iter, "{si}", &route_dest, &route_prefix)) {
-                               int tmp_route_len = strlen(route_dest);
-                               nets_vpn[i] = g_try_malloc0(sizeof(char) * tmp_route_len + 1);
-                               strncpy(nets_vpn[i], route_dest, tmp_route_len);
-                               nets_vpn[i][tmp_route_len] = '\0';
-                               prefix_vpn[i] = route_prefix;
-                               DBG("nets_vpn[%d] = %s \t", i, (nets_vpn[i] == NULL) ? "" : nets_vpn[i]);
-                               DBG("prefix_vpn[%d] = %d ", i, prefix_vpn[i]);
-                               i++;
+       if (arg_nr_nets_orig > MAX_NUM_ROUTE_RULE) {
+               ERR("Number of allowing networks over original interface is exceeded"
+                                               " %d, Limit is %d", arg_nr_nets_orig, MAX_NUM_ROUTE_RULE);
+               result = VPNSVC_ERROR_INVALID_PARAMETER;
+               goto method_complete;
+       }
+
+       do {
+               char *nets_vpn[arg_nr_nets_vpn];
+               int prefix_vpn[arg_nr_nets_vpn];
+
+               char *nets_orig[arg_nr_nets_orig];
+               int prefix_orig[arg_nr_nets_orig];
+
+               int i = 0;
+               GVariantIter iter;
+               gchar* route_dest;
+               gint route_prefix;
+
+               DBG("vpn_block_networks");
+
+               memset(nets_vpn, 0, sizeof(char *) * arg_nr_nets_vpn);
+               memset(prefix_vpn, 0, sizeof(int) * arg_nr_nets_vpn);
+               memset(nets_orig, 0, sizeof(char *) * arg_nr_nets_orig);
+               memset(prefix_orig, 0, sizeof(int) * arg_nr_nets_orig);
+
+               /* arg_nets_vpn check */
+               if (arg_nr_nets_vpn > 0) {
+                       if (arg_nets_vpn != NULL) {
+                               GVariant *dict_nets_vpn = g_variant_get_variant(arg_nets_vpn);
+                               g_variant_iter_init(&iter, dict_nets_vpn);
+                               i = 0;
+                               while (g_variant_iter_loop(&iter, "{si}", &route_dest, &route_prefix)) {
+                                       if (i >= arg_nr_nets_vpn) {
+                                               WARN("No more space for allowing network over VPN interface."
+                                                               " next index %d / space size %d", i, arg_nr_nets_vpn);
+                                               break;
+                                       }
+                                       int tmp_route_len = strlen(route_dest);
+                                       nets_vpn[i] = g_try_malloc0(sizeof(char) * tmp_route_len + 1);
+                                       strncpy(nets_vpn[i], route_dest, tmp_route_len);
+                                       nets_vpn[i][tmp_route_len] = '\0';
+                                       prefix_vpn[i] = route_prefix;
+                                       DBG("nets_vpn[%d] = %s \t", i, (nets_vpn[i] == NULL) ? "" : nets_vpn[i]);
+                                       DBG("prefix_vpn[%d] = %d ", i, prefix_vpn[i]);
+                                       i++;
+                               }
                        }
                }
-       }
 
-       /* arg_nets_orig check */
-       if (arg_nr_nets_orig > 0) {
-               if (arg_nets_orig != NULL) {
-                       GVariant *dict_nets_orig = g_variant_get_variant(arg_nets_orig);
-                       g_variant_iter_init(&iter, dict_nets_orig);
-                       i = 0;
-                       while (g_variant_iter_loop(&iter, "{si}", &route_dest, &route_prefix)) {
-                               int tmp_route_len = strlen(route_dest);
-                               nets_orig[i] = g_try_malloc0(sizeof(char) * tmp_route_len + 1);
-                               strncpy(nets_orig[i], route_dest, tmp_route_len);
-                               nets_orig[i][tmp_route_len] = '\0';
-                               prefix_orig[i] = route_prefix;
-                               DBG("nets_orig[%d] = %s \t", i, (nets_orig[i] == NULL) ? "" : nets_orig[i]);
-                               DBG("prefix_orig[%d] = %d ", i, prefix_orig[i]);
-                               i++;
+               /* arg_nets_orig check */
+               if (arg_nr_nets_orig > 0) {
+                       if (arg_nets_orig != NULL) {
+                               GVariant *dict_nets_orig = g_variant_get_variant(arg_nets_orig);
+                               g_variant_iter_init(&iter, dict_nets_orig);
+                               i = 0;
+                               while (g_variant_iter_loop(&iter, "{si}", &route_dest, &route_prefix)) {
+                                       if (i >= arg_nr_nets_orig) {
+                                               WARN("No more space for allowing network over VPN interface."
+                                                               " next index %d / space size %d", i, arg_nr_nets_orig);
+                                               break;
+                                       }
+                                       int tmp_route_len = strlen(route_dest);
+                                       nets_orig[i] = g_try_malloc0(sizeof(char) * tmp_route_len + 1);
+                                       strncpy(nets_orig[i], route_dest, tmp_route_len);
+                                       nets_orig[i][tmp_route_len] = '\0';
+                                       prefix_orig[i] = route_prefix;
+                                       DBG("nets_orig[%d] = %s \t", i, (nets_orig[i] == NULL) ? "" : nets_orig[i]);
+                                       DBG("prefix_orig[%d] = %d ", i, prefix_orig[i]);
+                                       i++;
+                               }
                        }
                }
-       }
 
-       /* call function */
-       result = vpn_service_block_networks(nets_vpn, prefix_vpn, arg_nr_nets_vpn, nets_orig, prefix_orig, arg_nr_nets_orig);
+               /* call function */
+               result = vpn_service_block_networks(nets_vpn, prefix_vpn, arg_nr_nets_vpn, nets_orig, prefix_orig, arg_nr_nets_orig);
 
-       for (i = 0; i < arg_nr_nets_vpn; ++i) {
-               g_free(nets_orig[i]);
-               g_free(nets_vpn[i]);
-       }
+               for (i = 0; i < arg_nr_nets_vpn; ++i) {
+                       g_free(nets_vpn[i]);
+               }
+
+               for (i = 0; i < arg_nr_nets_orig; ++i) {
+                       g_free(nets_orig[i]);
+               }
+       } while(0);
 
+method_complete:
        vpnsvc_complete_vpn_block_networks(object, invocation, result);
 
        return TRUE;