check string lengths inside of dynamically sized structs
authorDaniel Mack <zonque@gmail.com>
Sun, 15 Dec 2013 18:33:39 +0000 (19:33 +0100)
committerDaniel Mack <zonque@gmail.com>
Sun, 15 Dec 2013 18:33:39 +0000 (19:33 +0100)
connection.c
internal.h
names.c

index 891eaf8470286dce57424cb319313b2a3a342fff..cec26dadaa86878e4fd086e62d4c987519127029 100644 (file)
@@ -1227,6 +1227,11 @@ int kdbus_cmd_conn_info(struct kdbus_conn *conn,
        if (name) {
                struct kdbus_name_entry *e;
 
+               if (!kdbus_check_strlen(cmd_info, name)) {
+                       ret = -EINVAL;
+                       goto exit_free;
+               }
+
                e = kdbus_name_lookup(conn->ep->bus->name_registry, name);
                if (!e) {
                        ret = -ENOENT;
index 5b5b3c24b91bd9bfa4af712f078574d3743a777d..c6681009013af1b45ae567a7229ee4ceee856dc2 100644 (file)
        copy_to_user(_sz, _s, sizeof(__u64));                                   \
 })
 
+/**
+ * kdbus_check_strlen - check length of a string at the end a structure
+ * @_p:                        A pointer to a structure that has a size member and
+ *                     a variable string at its end
+ * @_s:                        The name of the dynamically sized string member
+ *
+ * Returns: 1 if the string's end marker is withing the struct, or 0 otherwise.
+ */
+#define kdbus_check_strlen(_p, _s)                                     \
+({                                                                     \
+       size_t _max = (_p)->size - offsetof(typeof(*(_p)), _s);         \
+       _max == 0 || strnlen((_p)->_s, _max) != _max;                   \
+})
+
 /**
  * kdbus_validate_nul - check the validity of a sized string
  * @s:                 String
diff --git a/names.c b/names.c
index cebcc6ded24dac1365c978fe83575b5badcc7628..a389e60fdc9479ccdc66be1836abb60641c255b2 100644 (file)
--- a/names.c
+++ b/names.c
@@ -496,7 +496,8 @@ int kdbus_cmd_name_acquire(struct kdbus_name_registry *reg,
        if (IS_ERR(cmd_name))
                return PTR_ERR(cmd_name);
 
-       if (!kdbus_name_is_valid(cmd_name->name)) {
+       if (!kdbus_check_strlen(cmd_name, name) ||
+           !kdbus_name_is_valid(cmd_name->name)) {
                ret = -EINVAL;
                goto exit_free;
        }