diff options
author | Tobias Schramm <tobleminer@gmail.com> | 2018-11-13 06:16:12 +0300 |
---|---|---|
committer | Petr Štetiar <ynezz@true.cz> | 2019-12-25 12:31:58 +0300 |
commit | cd3059796a576673d4af696c8b696ab5de729a3c (patch) | |
tree | 7d9b9922c45f9e9cba41827920c46b2b69d12afe /blobmsg.c | |
parent | 143303149c8b87fec76b7f2f4b365baae1e18d2c (diff) |
Replace use of blobmsg_check_attr by blobmsg_check_attr_len
blobmsg_check_attr_len adds a length limit specifying the max offset
from attr that can be read safely.
Signed-off-by: Tobias Schramm <tobleminer@gmail.com>
[rebased and reworked, line wrapped commit message, _safe -> _len]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
Diffstat (limited to 'blobmsg.c')
-rw-r--r-- | blobmsg.c | 60 |
1 files changed, 46 insertions, 14 deletions
@@ -33,38 +33,70 @@ blobmsg_namelen(const struct blobmsg_hdr *hdr) bool blobmsg_check_attr(const struct blob_attr *attr, bool name) { + return blobmsg_check_attr_len(attr, name, blob_raw_len(attr)); +} + +static bool blobmsg_check_name(const struct blob_attr *attr, size_t len, bool name) +{ + char *limit = (char *) attr + len; const struct blobmsg_hdr *hdr; - const char *data; - size_t len; - int id; - if (blob_len(attr) < sizeof(struct blobmsg_hdr)) + hdr = blob_data(attr); + if (name && !hdr->namelen) return false; - hdr = (void *) attr->data; - if (!hdr->namelen && name) + if ((char *) hdr->name + blobmsg_namelen(hdr) > limit) return false; - if (blobmsg_namelen(hdr) > blob_len(attr) - sizeof(struct blobmsg_hdr)) + if (blobmsg_namelen(hdr) > (blob_len(attr) - sizeof(struct blobmsg_hdr))) return false; if (hdr->name[blobmsg_namelen(hdr)] != 0) return false; - id = blob_id(attr); - len = blobmsg_data_len(attr); - if (len > blob_raw_len(attr)) - return false; + return true; +} + +static const char* blobmsg_check_data(const struct blob_attr *attr, size_t len, size_t *data_len) +{ + char *limit = (char *) attr + len; + const char *data; + + *data_len = blobmsg_data_len(attr); + if (*data_len > blob_raw_len(attr)) + return NULL; data = blobmsg_data(attr); + if (data + *data_len > limit) + return NULL; + + return data; +} + +bool blobmsg_check_attr_len(const struct blob_attr *attr, bool name, size_t len) +{ + const char *data; + size_t data_len; + int id; + if (len < sizeof(struct blob_attr)) + return false; + + if (!blobmsg_check_name(attr, len, name)) + return false; + + id = blob_id(attr); if (id > BLOBMSG_TYPE_LAST) return false; if (!blob_type[id]) return true; - return blob_check_type(data, len, blob_type[id]); + data = blobmsg_check_data(attr, len, &data_len); + if (!data) + return false; + + return blob_check_type(data, data_len, blob_type[id]); } int blobmsg_check_array(const struct blob_attr *attr, int type) @@ -115,7 +147,7 @@ int blobmsg_parse_array(const struct blobmsg_policy *policy, int policy_len, blob_id(attr) != policy[i].type) continue; - if (!blobmsg_check_attr(attr, false)) + if (!blobmsg_check_attr_len(attr, false, len)) return -1; if (tb[i]) @@ -162,7 +194,7 @@ int blobmsg_parse(const struct blobmsg_policy *policy, int policy_len, if (blobmsg_namelen(hdr) != pslen[i]) continue; - if (!blobmsg_check_attr(attr, true)) + if (!blobmsg_check_attr_len(attr, true, len)) return -1; if (tb[i]) |