Merge tag 'mvebu-dt-5.1-2' of git://git.infradead.org/linux-mvebu into arm/dt
[sfrench/cifs-2.6.git] / net / tipc / netlink_compat.c
index 77e4b2418f302555acac4813d3baa39b356e632e..4ad3586da8f028c0fb8244382b343a1c7635f6cb 100644 (file)
@@ -87,6 +87,11 @@ static int tipc_skb_tailroom(struct sk_buff *skb)
        return limit;
 }
 
+static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv)
+{
+       return TLV_GET_LEN(tlv) - TLV_SPACE(0);
+}
+
 static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
 {
        struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb);
@@ -166,6 +171,11 @@ static struct sk_buff *tipc_get_err_tlv(char *str)
        return buf;
 }
 
+static inline bool string_is_valid(char *s, int len)
+{
+       return memchr(s, '\0', len) ? true : false;
+}
+
 static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
                                   struct tipc_nl_compat_msg *msg,
                                   struct sk_buff *arg)
@@ -379,6 +389,7 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_bearer_config *b;
+       int len;
 
        b = (struct tipc_bearer_config *)TLV_DATA(msg->req);
 
@@ -386,6 +397,10 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(b->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name))
                return -EMSGSIZE;
 
@@ -411,6 +426,7 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *bearer;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -418,6 +434,10 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name))
                return -EMSGSIZE;
 
@@ -478,6 +498,7 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
        struct nlattr *prop[TIPC_NLA_PROP_MAX + 1];
        struct nlattr *stats[TIPC_NLA_STATS_MAX + 1];
        int err;
+       int len;
 
        if (!attrs[TIPC_NLA_LINK])
                return -EINVAL;
@@ -504,6 +525,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
                return err;
 
        name = (char *)TLV_DATA(msg->req);
+
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0)
                return 0;
 
@@ -644,6 +670,7 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *media;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -651,6 +678,10 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        if (!media)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -671,6 +702,7 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -678,6 +710,10 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -726,9 +762,14 @@ static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
        struct tipc_link_config *lc;
        struct tipc_bearer *bearer;
        struct tipc_media *media;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        media = tipc_media_find(lc->name);
        if (media) {
                cmd->doit = &__tipc_nl_media_set;
@@ -750,6 +791,7 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *link;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -757,6 +799,10 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
        if (!link)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name))
                return -EMSGSIZE;
 
@@ -778,6 +824,8 @@ static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg)
        };
 
        ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req);
+       if (TLV_GET_DATA_LEN(msg->req) < sizeof(struct tipc_name_table_query))
+               return -EINVAL;
 
        depth = ntohl(ntq->depth);
 
@@ -1208,7 +1256,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
        }
 
        len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-       if (len && !TLV_OK(msg.req, len)) {
+       if (!len || !TLV_OK(msg.req, len)) {
                msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
                err = -EOPNOTSUPP;
                goto send;