diff options
author | David Fries <David@Fries.net> | 2014-11-10 21:19:36 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-11-26 22:09:01 -0500 |
commit | a30cfa475d1a26c18f1998ba1e034a4e2ab4c7a8 (patch) | |
tree | 0d352909e457fca03a206f1a7fe10174ed7e5ba9 /drivers/connector | |
parent | 55c4e6405d434e2db1e3fb3618b84741bb17d862 (diff) |
cn: verify msg->len before making callback
The struct cn_msg len field comes from userspace and needs to be
validated. More logical to do so here where the cn_msg pointer is
pulled out of the sk_buff than the callback which is passed cn_msg *
and might assume no validation is needed.
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Acked-by: Evgeniy Polyakov <zbr@ioremap.net>
Signed-off-by: David Fries <David@Fries.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/connector')
-rw-r--r-- | drivers/connector/connector.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index f612d68629dc..30f522848c73 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c | |||
@@ -141,12 +141,18 @@ EXPORT_SYMBOL_GPL(cn_netlink_send); | |||
141 | */ | 141 | */ |
142 | static int cn_call_callback(struct sk_buff *skb) | 142 | static int cn_call_callback(struct sk_buff *skb) |
143 | { | 143 | { |
144 | struct nlmsghdr *nlh; | ||
144 | struct cn_callback_entry *i, *cbq = NULL; | 145 | struct cn_callback_entry *i, *cbq = NULL; |
145 | struct cn_dev *dev = &cdev; | 146 | struct cn_dev *dev = &cdev; |
146 | struct cn_msg *msg = nlmsg_data(nlmsg_hdr(skb)); | 147 | struct cn_msg *msg = nlmsg_data(nlmsg_hdr(skb)); |
147 | struct netlink_skb_parms *nsp = &NETLINK_CB(skb); | 148 | struct netlink_skb_parms *nsp = &NETLINK_CB(skb); |
148 | int err = -ENODEV; | 149 | int err = -ENODEV; |
149 | 150 | ||
151 | /* verify msg->len is within skb */ | ||
152 | nlh = nlmsg_hdr(skb); | ||
153 | if (nlh->nlmsg_len < NLMSG_HDRLEN + sizeof(struct cn_msg) + msg->len) | ||
154 | return -EINVAL; | ||
155 | |||
150 | spin_lock_bh(&dev->cbdev->queue_lock); | 156 | spin_lock_bh(&dev->cbdev->queue_lock); |
151 | list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) { | 157 | list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) { |
152 | if (cn_cb_equal(&i->id.id, &msg->id)) { | 158 | if (cn_cb_equal(&i->id.id, &msg->id)) { |