| From 3f685202f015dfd105c0e1871ac856b006fc3c55 Mon Sep 17 00:00:00 2001 |
| From: Ben Hutchings <bhutchings@solarflare.com> |
| Date: Tue, 7 Sep 2010 04:35:19 +0000 |
| Subject: niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL |
| |
| From: Ben Hutchings <bhutchings@solarflare.com> |
| |
| commit ee9c5cfad29c8a13199962614b9b16f1c4137ac9 upstream. |
| |
| niu_get_ethtool_tcam_all() assumes that its output buffer is the right |
| size, and warns before returning if it is not. However, the output |
| buffer size is under user control and ETHTOOL_GRXCLSRLALL is an |
| unprivileged ethtool command. Therefore this is at least a local |
| denial-of-service vulnerability. |
| |
| Change it to check before writing each entry and to return an error if |
| the buffer is already full. |
| |
| Compile-tested only. |
| |
| Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| [Adjusted to apply to 2.6.32 by dann frazier <dannf@debian.org>] |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| drivers/net/niu.c | 17 ++++++----------- |
| 1 file changed, 6 insertions(+), 11 deletions(-) |
| |
| --- a/drivers/net/niu.c |
| +++ b/drivers/net/niu.c |
| @@ -7315,33 +7315,28 @@ static int niu_get_ethtool_tcam_all(stru |
| struct niu_parent *parent = np->parent; |
| struct niu_tcam_entry *tp; |
| int i, idx, cnt; |
| - u16 n_entries; |
| unsigned long flags; |
| - |
| + int ret = 0; |
| |
| /* put the tcam size here */ |
| nfc->data = tcam_get_size(np); |
| |
| niu_lock_parent(np, flags); |
| - n_entries = nfc->rule_cnt; |
| for (cnt = 0, i = 0; i < nfc->data; i++) { |
| idx = tcam_get_index(np, i); |
| tp = &parent->tcam[idx]; |
| if (!tp->valid) |
| continue; |
| + if (cnt == nfc->rule_cnt) { |
| + ret = -EMSGSIZE; |
| + break; |
| + } |
| rule_locs[cnt] = i; |
| cnt++; |
| } |
| niu_unlock_parent(np, flags); |
| |
| - if (n_entries != cnt) { |
| - /* print warning, this should not happen */ |
| - pr_info(PFX "niu%d: %s In niu_get_ethtool_tcam_all, " |
| - "n_entries[%d] != cnt[%d]!!!\n\n", |
| - np->parent->index, np->dev->name, n_entries, cnt); |
| - } |
| - |
| - return 0; |
| + return ret; |
| } |
| |
| static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd, |