diff options
author | JP Abgrall <jpa@google.com> | 2011-10-09 02:33:17 +0100 |
---|---|---|
committer | Andy Green <andy.green@linaro.org> | 2011-10-09 02:33:17 +0100 |
commit | c99d5cc45a2f515d91d93cf28aaa6f91099cb0c4 (patch) | |
tree | c9d2f4243503b55db0025b3db7661dc14247a022 | |
parent | b21d9f29d081c8ef50fe0d637f2e6e3bd7429a98 (diff) |
netfilter: qtaguid: fix proc/.../stats uid filtered output
"cat /proc/net/xt_qtaguid/stats"
for a non-priviledged UID would output multiple twice its own stats.
The fix tweaks the way lines are counted.
Non-root:
idx iface acct_tag_hex uid_tag_int cnt_set ...
2 wlan0 0x0 10022 0 ...
3 wlan0 0x0 10022 1 ...
4 wlan0 0x3010000000000000 10022 0 ...
5 wlan0 0x3010000000000000 10022 1 ...
Root:
idx iface acct_tag_hex uid_tag_int cnt_set
2 wlan0 0x0 0 0 ...
3 wlan0 0x0 0 1 ...
4 wlan0 0x0 1000 0 ...
...
12 wlan0 0x0 10022 0 ...
13 wlan0 0x0 10022 1 ...
...
18 wlan0 0x3010000000000000 10022 0 ...
19 wlan0 0x3010000000000000 10022 1 ...
Change-Id: I3cae1f4fee616bc897831350374656b0c718c45b
Signed-off-by: JP Abgrall <jpa@google.com>
-rw-r--r-- | net/netfilter/xt_qtaguid.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 80b5990045b..b145f5a4b45 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1788,6 +1788,7 @@ struct proc_print_info { struct iface_stat *iface_entry; struct tag_stat *ts_entry; int item_index; + int items_to_skip; int char_count; }; @@ -1795,7 +1796,10 @@ static int pp_stats_line(struct proc_print_info *ppi, int cnt_set) { int len; struct data_counters *cnts; + if (!ppi->item_index) { + if (ppi->item_index++ < ppi->items_to_skip) + return 0; len = snprintf(ppi->outp, ppi->char_count, "idx iface acct_tag_hex uid_tag_int cnt_set " "rx_bytes rx_packets " @@ -1809,6 +1813,7 @@ static int pp_stats_line(struct proc_print_info *ppi, int cnt_set) } else { tag_t tag = ppi->ts_entry->tn.tag; uid_t stat_uid = get_uid_from_tag(tag); + if (!can_read_other_uid_stats(stat_uid)) { CT_DEBUG("qtaguid: stats line: " "%s 0x%llx %u: " @@ -1818,6 +1823,8 @@ static int pp_stats_line(struct proc_print_info *ppi, int cnt_set) current->pid, current_fsuid()); return 0; } + if (ppi->item_index++ < ppi->items_to_skip) + return 0; cnts = &ppi->ts_entry->counters; len = snprintf( ppi->outp, ppi->char_count, @@ -1891,11 +1898,13 @@ static int qtaguid_stats_proc_read(char *page, char **num_items_returned, ppi.item_index = 0; ppi.char_count = char_count; ppi.num_items_returned = num_items_returned; + ppi.items_to_skip = items_to_skip; if (unlikely(module_passive)) { len = pp_stats_line(&ppi, 0); /* The header should always be shorter than the buffer. */ WARN_ON(len >= ppi.char_count); + (*num_items_returned)++; *eof = 1; return len; } @@ -1907,16 +1916,17 @@ static int qtaguid_stats_proc_read(char *page, char **num_items_returned, if (*eof) return 0; - if (!items_to_skip) { - /* The idx is there to help debug when things go belly up. */ - len = pp_stats_line(&ppi, 0); - /* Don't advance the outp unless the whole line was printed */ - if (len >= ppi.char_count) { - *ppi.outp = '\0'; - return ppi.outp - page; - } + /* The idx is there to help debug when things go belly up. */ + len = pp_stats_line(&ppi, 0); + /* Don't advance the outp unless the whole line was printed */ + if (len >= ppi.char_count) { + *ppi.outp = '\0'; + return ppi.outp - page; + } + if (len) { ppi.outp += len; ppi.char_count -= len; + (*num_items_returned)++; } spin_lock_bh(&iface_stat_list_lock); @@ -1927,8 +1937,6 @@ static int qtaguid_stats_proc_read(char *page, char **num_items_returned, node; node = rb_next(node)) { ppi.ts_entry = rb_entry(node, struct tag_stat, tn.node); - if (ppi.item_index++ < items_to_skip) - continue; if (!pp_sets(&ppi)) { spin_unlock_bh( &ppi.iface_entry->tag_stat_list_lock); |