mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 14:42:37 +02:00
netfilter: xt_qtaguid: fix crash after using delete ctrl command
* Crash fix
The delete command would delete a socket tag entry without removing it
from the proc_qtu_data { ..., sock_tag_list, }.
This in turn would cause an exiting process to crash while cleaning up
its matching proc_qtu_data.
* Added more aggressive tracking/cleanup of proc_qtu_data
This should allow one process to cleanup qtu_tag_data{} left around from
processes that didn't use resource tracking via /dev/xt_qtaguid.
* Debug printing tweaks
Better code inclusion/exclusion handling,
and extra debug out of full state.
Change-Id: I735965af2962ffcd7f3021cdc0068b3ab21245c2
Signed-off-by: JP Abgrall <jpa@google.com>
This commit is contained in:
parent
b1d0d5fe07
commit
c843dede96
|
|
@ -102,11 +102,10 @@ static bool qtu_proc_handling_passive;
|
|||
module_param_named(tag_tracking_passive, qtu_proc_handling_passive, bool,
|
||||
S_IRUGO | S_IWUSR);
|
||||
|
||||
|
||||
#define QTU_DEV_NAME "xt_qtaguid"
|
||||
|
||||
uint debug_mask = DEFAULT_DEBUG_MASK;
|
||||
module_param(debug_mask, uint, S_IRUGO | S_IWUSR);
|
||||
uint qtaguid_debug_mask = DEFAULT_DEBUG_MASK;
|
||||
module_param_named(debug_mask, qtaguid_debug_mask, uint, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static const char *iface_stat_procdirname = "iface_stat";
|
||||
|
|
@ -125,70 +124,92 @@ static struct proc_dir_entry *iface_stat_all_procfile;
|
|||
* Notice how sock_tag_list_lock is held sometimes when uid_tag_data_tree_lock
|
||||
* is acquired.
|
||||
*
|
||||
* Call tree with all lock holders as of 2011-09-06:
|
||||
* Call tree with all lock holders as of 2011-09-25:
|
||||
*
|
||||
* qtaguid_ctrl_parse()
|
||||
* ctrl_cmd_delete()
|
||||
* sock_tag_list_lock
|
||||
* tag_counter_set_list_lock
|
||||
* iface_stat_list_lock
|
||||
* iface_entry->tag_stat_list_lock
|
||||
* uid_tag_data_tree_lock
|
||||
* ctrl_cmd_counter_set()
|
||||
* tag_counter_set_list_lock
|
||||
* ctrl_cmd_tag()
|
||||
* sock_tag_list_lock
|
||||
* get_tag_ref()
|
||||
* uid_tag_data_tree_lock
|
||||
* uid_tag_data_tree_lock
|
||||
* ctrl_cmd_untag()
|
||||
* sock_tag_list_lock
|
||||
* iface_stat_all_proc_read()
|
||||
* iface_stat_list_lock
|
||||
* (struct iface_stat)
|
||||
*
|
||||
* qtaguid_ctrl_proc_read()
|
||||
* sock_tag_list_lock
|
||||
* (sock_tag_tree)
|
||||
* (struct proc_qtu_data->sock_tag_list)
|
||||
* prdebug_full_state()
|
||||
* sock_tag_list_lock
|
||||
* (sock_tag_tree)
|
||||
* uid_tag_data_tree_lock
|
||||
* (uid_tag_data_tree)
|
||||
* (proc_qtu_data_tree)
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* qtaguid_stats_proc_read()
|
||||
* iface_stat_list_lock
|
||||
* struct iface_stat->tag_stat_list_lock
|
||||
*
|
||||
* qtudev_open()
|
||||
* uid_tag_data_tree_lock
|
||||
*
|
||||
* qtudev_release()
|
||||
* sock_tag_data_list_lock
|
||||
* uid_tag_data_tree_lock
|
||||
* prdebug_full_state()
|
||||
* sock_tag_list_lock
|
||||
* uid_tag_data_tree_lock
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* iface_netdev_event_handler()
|
||||
* iface_stat_create()
|
||||
* iface_stat_list_lock
|
||||
* iface_stat_update()
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* iface_inetaddr_event_handler()
|
||||
* iface_stat_create()
|
||||
* iface_stat_list_lock
|
||||
* iface_stat_update()
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* iface_inet6addr_event_handler()
|
||||
* iface_stat_create_ipv6()
|
||||
* iface_stat_list_lock
|
||||
* iface_stat_update()
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* qtaguid_mt()
|
||||
* account_for_uid()
|
||||
* if_tag_stat_update()
|
||||
* get_sock_stat()
|
||||
* sock_tag_list_lock
|
||||
* struct iface_stat->tag_stat_list_lock
|
||||
* tag_stat_update()
|
||||
* get_active_counter_set()
|
||||
* tag_counter_set_list_lock
|
||||
* tag_stat_update()
|
||||
* get_active_counter_set()
|
||||
* tag_counter_set_list_lock
|
||||
*
|
||||
*
|
||||
* qtaguid_ctrl_parse()
|
||||
* ctrl_cmd_delete()
|
||||
* sock_tag_list_lock
|
||||
* tag_counter_set_list_lock
|
||||
* iface_stat_list_lock
|
||||
* struct iface_stat->tag_stat_list_lock
|
||||
* uid_tag_data_tree_lock
|
||||
* ctrl_cmd_counter_set()
|
||||
* tag_counter_set_list_lock
|
||||
* ctrl_cmd_tag()
|
||||
* sock_tag_list_lock
|
||||
* (sock_tag_tree)
|
||||
* get_tag_ref()
|
||||
* uid_tag_data_tree_lock
|
||||
*
|
||||
* qtaguid_mt()
|
||||
* account_for_uid()
|
||||
* if_tag_stat_update()
|
||||
* get_sock_stat()
|
||||
* sock_tag_list_lock
|
||||
* iface_entry->tag_stat_list_lock
|
||||
* tag_stat_update()
|
||||
* get_active_counter_set()
|
||||
* tag_counter_set_list_lock
|
||||
*
|
||||
* iface_netdev_event_handler()
|
||||
* iface_stat_create()
|
||||
* iface_stat_list_lock
|
||||
* iface_stat_update()
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* iface_inet6addr_event_handler()
|
||||
* iface_stat_create_ipv6()
|
||||
* iface_stat_list_lock
|
||||
* iface_stat_update()
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* iface_inetaddr_event_handler()
|
||||
* iface_stat_create()
|
||||
* iface_stat_list_lock
|
||||
* iface_stat_update()
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* qtaguid_ctrl_proc_read()
|
||||
* sock_tag_list_lock
|
||||
* sock_tag_list_lock
|
||||
* uid_tag_data_tree_lock
|
||||
* iface_stat_list_lock
|
||||
*
|
||||
* qtaguid_stats_proc_read()
|
||||
* iface_stat_list_lock
|
||||
* iface_entry->tag_stat_list_lock
|
||||
*
|
||||
* qtudev_open()
|
||||
* uid_tag_data_tree_lock
|
||||
*
|
||||
* qtud_dev_release()
|
||||
* sock_tag_list_lock
|
||||
* (uid_tag_data_tree)
|
||||
* uid_tag_data_tree_lock
|
||||
* (proc_qtu_data_tree)
|
||||
* ctrl_cmd_untag()
|
||||
* sock_tag_list_lock
|
||||
* uid_tag_data_tree_lock
|
||||
*
|
||||
*/
|
||||
static LIST_HEAD(iface_stat_list);
|
||||
static DEFINE_SPINLOCK(iface_stat_list_lock);
|
||||
|
|
@ -557,8 +578,8 @@ static struct tag_ref *new_tag_ref(tag_t new_tag,
|
|||
utd_entry->num_active_tags++;
|
||||
tag_ref_tree_insert(tr_entry, &utd_entry->tag_ref_tree);
|
||||
DR_DEBUG("qtaguid: new_tag_ref(0x%llx): "
|
||||
" inserted new tag ref\n",
|
||||
new_tag);
|
||||
" inserted new tag ref %p\n",
|
||||
new_tag, tr_entry);
|
||||
return tr_entry;
|
||||
|
||||
err_res:
|
||||
|
|
@ -618,7 +639,8 @@ static struct tag_ref *get_tag_ref(tag_t full_tag,
|
|||
static void put_utd_entry(struct uid_tag_data *utd_entry)
|
||||
{
|
||||
/* Are we done with the UID tag data entry? */
|
||||
if (RB_EMPTY_ROOT(&utd_entry->tag_ref_tree)) {
|
||||
if (RB_EMPTY_ROOT(&utd_entry->tag_ref_tree) &&
|
||||
!utd_entry->num_pqd) {
|
||||
DR_DEBUG("qtaguid: %s(): "
|
||||
"erase utd_entry=%p uid=%u "
|
||||
"by pid=%u tgid=%u uid=%u\n", __func__,
|
||||
|
|
@ -629,9 +651,11 @@ static void put_utd_entry(struct uid_tag_data *utd_entry)
|
|||
kfree(utd_entry);
|
||||
} else {
|
||||
DR_DEBUG("qtaguid: %s(): "
|
||||
"utd_entry=%p still has %d tags\n", __func__,
|
||||
utd_entry, utd_entry->num_active_tags);
|
||||
BUG_ON(!utd_entry->num_active_tags);
|
||||
"utd_entry=%p still has %d tags %d proc_qtu_data\n",
|
||||
__func__, utd_entry, utd_entry->num_active_tags,
|
||||
utd_entry->num_pqd);
|
||||
BUG_ON(!(utd_entry->num_active_tags ||
|
||||
utd_entry->num_pqd));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1309,8 +1333,8 @@ static void if_tag_stat_update(const char *ifname, uid_t uid,
|
|||
new_tag_stat = create_if_tag_stat(iface_entry, tag);
|
||||
new_tag_stat->parent_counters = uid_tag_counters;
|
||||
}
|
||||
spin_unlock_bh(&iface_entry->tag_stat_list_lock);
|
||||
tag_stat_update(new_tag_stat, direction, proto, bytes);
|
||||
spin_unlock_bh(&iface_entry->tag_stat_list_lock);
|
||||
}
|
||||
|
||||
static int iface_netdev_event_handler(struct notifier_block *nb,
|
||||
|
|
@ -1672,6 +1696,50 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
|
|||
return res;
|
||||
}
|
||||
|
||||
#ifdef DDEBUG
|
||||
/* This function is not in xt_qtaguid_print.c because of locks visibility */
|
||||
static void prdebug_full_state(int indent_level, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *fmt_buff;
|
||||
char *buff;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
fmt_buff = kasprintf(GFP_ATOMIC,
|
||||
"qtaguid: %s(): %s {\n", __func__, fmt);
|
||||
BUG_ON(!fmt_buff);
|
||||
va_start(args, fmt);
|
||||
buff = kvasprintf(GFP_ATOMIC,
|
||||
fmt_buff, args);
|
||||
BUG_ON(!buff);
|
||||
pr_debug("%s", buff);
|
||||
kfree(fmt_buff);
|
||||
kfree(buff);
|
||||
va_end(args);
|
||||
|
||||
spin_lock_bh(&sock_tag_list_lock);
|
||||
prdebug_sock_tag_tree(indent_level, &sock_tag_tree);
|
||||
spin_unlock_bh(&sock_tag_list_lock);
|
||||
|
||||
spin_lock_bh(&sock_tag_list_lock);
|
||||
spin_lock_bh(&uid_tag_data_tree_lock);
|
||||
prdebug_uid_tag_data_tree(indent_level, &uid_tag_data_tree);
|
||||
prdebug_proc_qtu_data_tree(indent_level, &proc_qtu_data_tree);
|
||||
spin_unlock_bh(&uid_tag_data_tree_lock);
|
||||
spin_unlock_bh(&sock_tag_list_lock);
|
||||
|
||||
spin_lock_bh(&iface_stat_list_lock);
|
||||
prdebug_iface_stat_list(indent_level, &iface_stat_list);
|
||||
spin_unlock_bh(&iface_stat_list_lock);
|
||||
|
||||
pr_debug("qtaguid: %s(): }\n", __func__);
|
||||
}
|
||||
#else
|
||||
static void prdebug_full_state(int indent_level, const char *fmt, ...) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Procfs reader to get all active socket tags using style "1)" as described in
|
||||
* fs/proc/generic.c
|
||||
|
|
@ -1761,28 +1829,10 @@ static int qtaguid_ctrl_proc_read(char *page, char **num_items_returned,
|
|||
(*num_items_returned)++;
|
||||
}
|
||||
|
||||
#ifdef CDEBUG
|
||||
/* Count the following as part of the last item_index */
|
||||
if (item_index > items_to_skip) {
|
||||
CT_DEBUG("qtaguid: proc ctrl state debug {\n");
|
||||
spin_lock_bh(&sock_tag_list_lock);
|
||||
prdebug_sock_tag_tree(indent_level, &sock_tag_tree);
|
||||
spin_unlock_bh(&sock_tag_list_lock);
|
||||
|
||||
spin_lock_bh(&uid_tag_data_tree_lock);
|
||||
prdebug_uid_tag_data_tree(indent_level, &uid_tag_data_tree);
|
||||
prdebug_proc_qtu_data_tree(indent_level, &proc_qtu_data_tree);
|
||||
spin_unlock_bh(&uid_tag_data_tree_lock);
|
||||
|
||||
spin_lock_bh(&iface_stat_list_lock);
|
||||
prdebug_iface_stat_list(indent_level, &iface_stat_list);
|
||||
spin_unlock_bh(&iface_stat_list_lock);
|
||||
|
||||
CT_DEBUG("qtaguid: proc ctrl state debug }\n");
|
||||
|
||||
|
||||
prdebug_full_state(indent_level, "proc ctrl");
|
||||
}
|
||||
#endif
|
||||
|
||||
*eof = 1;
|
||||
return outp - page;
|
||||
|
|
@ -1833,9 +1883,9 @@ static int ctrl_cmd_delete(const char *input)
|
|||
}
|
||||
|
||||
tag = combine_atag_with_uid(acct_tag, uid);
|
||||
CT_DEBUG("qtaguid: ctrl_delete(): "
|
||||
CT_DEBUG("qtaguid: ctrl_delete(%s): "
|
||||
"looking for tag=0x%llx (uid=%u)\n",
|
||||
tag, uid);
|
||||
input, tag, uid);
|
||||
|
||||
/* Delete socket tags */
|
||||
spin_lock_bh(&sock_tag_list_lock);
|
||||
|
|
@ -1847,8 +1897,8 @@ static int ctrl_cmd_delete(const char *input)
|
|||
if (entry_uid != uid)
|
||||
continue;
|
||||
|
||||
CT_DEBUG("qtaguid: ctrl_delete(): st tag=0x%llx (uid=%u)\n",
|
||||
st_entry->tag, entry_uid);
|
||||
CT_DEBUG("qtaguid: ctrl_delete(%s): st tag=0x%llx (uid=%u)\n",
|
||||
input, st_entry->tag, entry_uid);
|
||||
|
||||
if (!acct_tag || st_entry->tag == tag) {
|
||||
rb_erase(&st_entry->sock_node, &sock_tag_tree);
|
||||
|
|
@ -1857,6 +1907,7 @@ static int ctrl_cmd_delete(const char *input)
|
|||
tr_entry = lookup_tag_ref(st_entry->tag, NULL);
|
||||
BUG_ON(tr_entry->num_sock_tags <= 0);
|
||||
tr_entry->num_sock_tags--;
|
||||
list_del(&st_entry->list);
|
||||
}
|
||||
}
|
||||
spin_unlock_bh(&sock_tag_list_lock);
|
||||
|
|
@ -1868,8 +1919,9 @@ static int ctrl_cmd_delete(const char *input)
|
|||
/* Counter sets are only on the uid tag, not full tag */
|
||||
tcs_entry = tag_counter_set_tree_search(&tag_counter_set_tree, tag);
|
||||
if (tcs_entry) {
|
||||
CT_DEBUG("qtaguid: ctrl_delete(): "
|
||||
CT_DEBUG("qtaguid: ctrl_delete(%s): "
|
||||
"erase tcs: tag=0x%llx (uid=%u) set=%d\n",
|
||||
input,
|
||||
tcs_entry->tn.tag,
|
||||
get_uid_from_tag(tcs_entry->tn.tag),
|
||||
tcs_entry->active_set);
|
||||
|
|
@ -1891,16 +1943,16 @@ static int ctrl_cmd_delete(const char *input)
|
|||
entry_uid = get_uid_from_tag(ts_entry->tn.tag);
|
||||
node = rb_next(node);
|
||||
|
||||
CT_DEBUG("qtaguid: ctrl_delete(): "
|
||||
CT_DEBUG("qtaguid: ctrl_delete(%s): "
|
||||
"ts tag=0x%llx (uid=%u)\n",
|
||||
ts_entry->tn.tag, entry_uid);
|
||||
input, ts_entry->tn.tag, entry_uid);
|
||||
|
||||
if (entry_uid != uid)
|
||||
continue;
|
||||
if (!acct_tag || ts_entry->tn.tag == tag) {
|
||||
CT_DEBUG("qtaguid: ctrl_delete(): "
|
||||
CT_DEBUG("qtaguid: ctrl_delete(%s): "
|
||||
"erase ts: %s 0x%llx %u\n",
|
||||
iface_entry->ifname,
|
||||
input, iface_entry->ifname,
|
||||
get_atag_from_tag(ts_entry->tn.tag),
|
||||
entry_uid);
|
||||
rb_erase(&ts_entry->tn.node,
|
||||
|
|
@ -1920,9 +1972,9 @@ static int ctrl_cmd_delete(const char *input)
|
|||
entry_uid = utd_entry->uid;
|
||||
node = rb_next(node);
|
||||
|
||||
CT_DEBUG("qtaguid: ctrl_delete(): "
|
||||
CT_DEBUG("qtaguid: ctrl_delete(%s): "
|
||||
"utd uid=%u\n",
|
||||
entry_uid);
|
||||
input, entry_uid);
|
||||
|
||||
if (entry_uid != uid)
|
||||
continue;
|
||||
|
|
@ -2377,7 +2429,7 @@ static int pp_stats_line(struct proc_print_info *ppi, int cnt_set)
|
|||
return len;
|
||||
}
|
||||
|
||||
bool pp_sets(struct proc_print_info *ppi)
|
||||
static bool pp_sets(struct proc_print_info *ppi)
|
||||
{
|
||||
int len;
|
||||
int counter_set;
|
||||
|
|
@ -2472,7 +2524,7 @@ static int qtudev_open(struct inode *inode, struct file *file)
|
|||
{
|
||||
struct uid_tag_data *utd_entry;
|
||||
struct proc_qtu_data *pqd_entry;
|
||||
struct proc_qtu_data *new_pqd_entry = 0;
|
||||
struct proc_qtu_data *new_pqd_entry;
|
||||
int res;
|
||||
bool utd_entry_found;
|
||||
|
||||
|
|
@ -2514,12 +2566,14 @@ static int qtudev_open(struct inode *inode, struct file *file)
|
|||
new_pqd_entry->pid = current->tgid;
|
||||
INIT_LIST_HEAD(&new_pqd_entry->sock_tag_list);
|
||||
new_pqd_entry->parent_tag_data = utd_entry;
|
||||
utd_entry->num_pqd++;
|
||||
|
||||
proc_qtu_data_tree_insert(new_pqd_entry,
|
||||
&proc_qtu_data_tree);
|
||||
|
||||
spin_unlock_bh(&uid_tag_data_tree_lock);
|
||||
DR_DEBUG("qtaguid: tracking data for uid=%u\n", current_fsuid());
|
||||
DR_DEBUG("qtaguid: tracking data for uid=%u in pqd=%p\n",
|
||||
current_fsuid(), new_pqd_entry);
|
||||
file->private_data = new_pqd_entry;
|
||||
return 0;
|
||||
|
||||
|
|
@ -2559,12 +2613,6 @@ static int qtudev_release(struct inode *inode, struct file *file)
|
|||
spin_lock_bh(&sock_tag_list_lock);
|
||||
spin_lock_bh(&uid_tag_data_tree_lock);
|
||||
|
||||
/*
|
||||
* If this proc didn't actually tag anything for itself, or has already
|
||||
* willingly cleaned up itself ...
|
||||
*/
|
||||
put_utd_entry(utd_entry);
|
||||
|
||||
list_for_each_safe(entry, next, &pqd_entry->sock_tag_list) {
|
||||
st_entry = list_entry(entry, struct sock_tag, list);
|
||||
DR_DEBUG("qtaguid: %s(): "
|
||||
|
|
@ -2593,10 +2641,18 @@ static int qtudev_release(struct inode *inode, struct file *file)
|
|||
/* Can't sockfd_put() within spinlock, do it later. */
|
||||
sock_tag_tree_insert(st_entry, &st_to_free_tree);
|
||||
|
||||
/* Do not put_utd_entry(utd_entry) someone elses utd_entry */
|
||||
/*
|
||||
* Try to free the utd_entry if no other proc_qtu_data is
|
||||
* using it (num_pqd is 0) and it doesn't have active tags
|
||||
* (num_active_tags is 0).
|
||||
*/
|
||||
put_utd_entry(utd_entry);
|
||||
}
|
||||
|
||||
rb_erase(&pqd_entry->node, &proc_qtu_data_tree);
|
||||
BUG_ON(pqd_entry->parent_tag_data->num_pqd < 1);
|
||||
pqd_entry->parent_tag_data->num_pqd--;
|
||||
put_utd_entry(pqd_entry->parent_tag_data);
|
||||
kfree(pqd_entry);
|
||||
file->private_data = NULL;
|
||||
|
||||
|
|
@ -2606,7 +2662,8 @@ static int qtudev_release(struct inode *inode, struct file *file)
|
|||
|
||||
sock_tag_tree_erase(&st_to_free_tree);
|
||||
|
||||
|
||||
prdebug_full_state(0, "%s(): pid=%u tgid=%u", __func__,
|
||||
current->pid, current->tgid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,31 +15,33 @@
|
|||
#include <linux/spinlock_types.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
/* Define/comment out these *DEBUG to compile in/out the pr_debug calls. */
|
||||
/* Iface handling */
|
||||
#define IDEBUG
|
||||
#define IDEBUG_MASK (1<<0)
|
||||
/* Iptable Matching. Per packet. */
|
||||
#define MDEBUG
|
||||
#define MDEBUG_MASK (1<<1)
|
||||
/* Red-black tree handling. Per packet. */
|
||||
#define RDEBUG
|
||||
#define RDEBUG_MASK (1<<2)
|
||||
/* procfs ctrl/stats handling */
|
||||
#define CDEBUG
|
||||
#define CDEBUG_MASK (1<<3)
|
||||
/* dev and resource tracking */
|
||||
#define DDEBUG
|
||||
#define DDEBUG_MASK (1<<4)
|
||||
|
||||
/* E.g (IDEBUG_MASK | CDEBUG_MASK | DDEBUG_MASK) */
|
||||
#define DEFAULT_DEBUG_MASK 0
|
||||
|
||||
/*
|
||||
* (Un)Define these *DEBUG to compile out/in the pr_debug calls.
|
||||
* All undef: text size ~ 0x3030; all def: ~ 0x4404.
|
||||
*/
|
||||
#define IDEBUG
|
||||
#define MDEBUG
|
||||
#define RDEBUG
|
||||
#define CDEBUG
|
||||
#define DDEBUG
|
||||
|
||||
#define IDEBUG_MASK (1<<0)
|
||||
#define MDEBUG_MASK (1<<1)
|
||||
#define RDEBUG_MASK (1<<2)
|
||||
#define CDEBUG_MASK (1<<3)
|
||||
#define DDEBUG_MASK (1<<4)
|
||||
|
||||
#define MSK_DEBUG(mask, ...) do { \
|
||||
if (unlikely(debug_mask & (mask))) \
|
||||
pr_debug(__VA_ARGS__); \
|
||||
#define MSK_DEBUG(mask, ...) do { \
|
||||
if (unlikely(qtaguid_debug_mask & (mask))) \
|
||||
pr_debug(__VA_ARGS__); \
|
||||
} while (0)
|
||||
#ifdef IDEBUG
|
||||
#define IF_DEBUG(...) MSK_DEBUG(IDEBUG_MASK, __VA_ARGS__)
|
||||
|
|
@ -67,7 +69,7 @@
|
|||
#define DR_DEBUG(...) no_printk(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
extern uint debug_mask;
|
||||
extern uint qtaguid_debug_mask;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
|
|
@ -286,6 +288,8 @@ struct uid_tag_data {
|
|||
* For the uid, how many accounting tags have been set.
|
||||
*/
|
||||
int num_active_tags;
|
||||
/* Track the number of proc_qtu_data that reference it */
|
||||
int num_pqd;
|
||||
struct rb_root tag_ref_tree;
|
||||
/* No tag_node_tree_lock; use uid_tag_data_tree_lock */
|
||||
};
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@
|
|||
*/
|
||||
|
||||
/*
|
||||
* There are run-time debug flags enabled via the debug_mask module param, or
|
||||
* via the DEFAULT_DEBUG_MASK. See xt_qtaguid_internal.h.
|
||||
* Most of the functions in this file just waste time if DEBUG is not defined.
|
||||
* The matching xt_qtaguid_print.h will static inline empty funcs if the needed
|
||||
* debug flags ore not defined.
|
||||
* Those funcs that fail to allocate memory will panic as there is no need to
|
||||
* hobble allong just pretending to do the requested work.
|
||||
*/
|
||||
|
||||
#define DEBUG
|
||||
|
||||
#include <linux/fs.h>
|
||||
|
|
@ -25,21 +29,38 @@
|
|||
#include "xt_qtaguid_internal.h"
|
||||
#include "xt_qtaguid_print.h"
|
||||
|
||||
#ifdef DDEBUG
|
||||
|
||||
static void _bug_on_err_or_null(void *ptr)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(ptr)) {
|
||||
pr_err("qtaguid: kmalloc failed\n");
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
char *pp_tag_t(tag_t *tag)
|
||||
{
|
||||
char *res;
|
||||
|
||||
if (!tag)
|
||||
return kasprintf(GFP_ATOMIC, "tag_t@null{}");
|
||||
return kasprintf(GFP_ATOMIC,
|
||||
"tag_t@%p{tag=0x%llx, uid=%u}",
|
||||
tag, *tag, get_uid_from_tag(*tag));
|
||||
res = kasprintf(GFP_ATOMIC, "tag_t@null{}");
|
||||
else
|
||||
res = kasprintf(GFP_ATOMIC,
|
||||
"tag_t@%p{tag=0x%llx, uid=%u}",
|
||||
tag, *tag, get_uid_from_tag(*tag));
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *pp_data_counters(struct data_counters *dc, bool showValues)
|
||||
{
|
||||
char *res;
|
||||
|
||||
if (!dc)
|
||||
return kasprintf(GFP_ATOMIC, "data_counters@null{}");
|
||||
if (showValues)
|
||||
return kasprintf(
|
||||
res = kasprintf(GFP_ATOMIC, "data_counters@null{}");
|
||||
else if (showValues)
|
||||
res = kasprintf(
|
||||
GFP_ATOMIC, "data_counters@%p{"
|
||||
"set0{"
|
||||
"rx{"
|
||||
|
|
@ -85,7 +106,9 @@ char *pp_data_counters(struct data_counters *dc, bool showValues)
|
|||
dc->bpc[1][IFS_TX][IFS_PROTO_OTHER].bytes,
|
||||
dc->bpc[1][IFS_TX][IFS_PROTO_OTHER].packets);
|
||||
else
|
||||
return kasprintf(GFP_ATOMIC, "data_counters@%p{...}", dc);
|
||||
res = kasprintf(GFP_ATOMIC, "data_counters@%p{...}", dc);
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *pp_tag_node(struct tag_node *tn)
|
||||
|
|
@ -93,12 +116,16 @@ char *pp_tag_node(struct tag_node *tn)
|
|||
char *tag_str;
|
||||
char *res;
|
||||
|
||||
if (!tn)
|
||||
return kasprintf(GFP_ATOMIC, "tag_node@null{}");
|
||||
if (!tn) {
|
||||
res = kasprintf(GFP_ATOMIC, "tag_node@null{}");
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
tag_str = pp_tag_t(&tn->tag);
|
||||
res = kasprintf(GFP_ATOMIC,
|
||||
"tag_node@%p{tag=%s}",
|
||||
tn, tag_str);
|
||||
_bug_on_err_or_null(res);
|
||||
kfree(tag_str);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -108,12 +135,16 @@ char *pp_tag_ref(struct tag_ref *tr)
|
|||
char *tn_str;
|
||||
char *res;
|
||||
|
||||
if (!tr)
|
||||
return kasprintf(GFP_ATOMIC, "tag_ref@null{}");
|
||||
if (!tr) {
|
||||
res = kasprintf(GFP_ATOMIC, "tag_ref@null{}");
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
tn_str = pp_tag_node(&tr->tn);
|
||||
res = kasprintf(GFP_ATOMIC,
|
||||
"tag_ref@%p{%s, num_sock_tags=%d}",
|
||||
tr, tn_str, tr->num_sock_tags);
|
||||
_bug_on_err_or_null(res);
|
||||
kfree(tn_str);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -125,14 +156,18 @@ char *pp_tag_stat(struct tag_stat *ts)
|
|||
char *parent_counters_str;
|
||||
char *res;
|
||||
|
||||
if (!ts)
|
||||
return kasprintf(GFP_ATOMIC, "tag_stat@null{}");
|
||||
if (!ts) {
|
||||
res = kasprintf(GFP_ATOMIC, "tag_stat@null{}");
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
tn_str = pp_tag_node(&ts->tn);
|
||||
counters_str = pp_data_counters(&ts->counters, true);
|
||||
parent_counters_str = pp_data_counters(ts->parent_counters, false);
|
||||
res = kasprintf(GFP_ATOMIC,
|
||||
"tag_stat@%p{%s, counters=%s, parent_counters=%s}",
|
||||
ts, tn_str, counters_str, parent_counters_str);
|
||||
_bug_on_err_or_null(res);
|
||||
kfree(tn_str);
|
||||
kfree(counters_str);
|
||||
kfree(parent_counters_str);
|
||||
|
|
@ -141,38 +176,42 @@ char *pp_tag_stat(struct tag_stat *ts)
|
|||
|
||||
char *pp_iface_stat(struct iface_stat *is)
|
||||
{
|
||||
char *res;
|
||||
if (!is)
|
||||
return kasprintf(GFP_ATOMIC, "iface_stat@null{}");
|
||||
return kasprintf(GFP_ATOMIC, "iface_stat@%p{"
|
||||
"list=list_head{...}, "
|
||||
"ifname=%s, "
|
||||
"total={rx={bytes=%llu, "
|
||||
"packets=%llu}, "
|
||||
"tx={bytes=%llu, "
|
||||
"packets=%llu}}, "
|
||||
"last_known_valid=%d, "
|
||||
"last_known={rx={bytes=%llu, "
|
||||
"packets=%llu}, "
|
||||
"tx={bytes=%llu, "
|
||||
"packets=%llu}}, "
|
||||
"active=%d, "
|
||||
"net_dev=%p, "
|
||||
"proc_ptr=%p, "
|
||||
"tag_stat_tree=rb_root{...}}",
|
||||
is,
|
||||
is->ifname,
|
||||
is->totals[IFS_RX].bytes,
|
||||
is->totals[IFS_RX].packets,
|
||||
is->totals[IFS_TX].bytes,
|
||||
is->totals[IFS_TX].packets,
|
||||
is->last_known_valid,
|
||||
is->last_known[IFS_RX].bytes,
|
||||
is->last_known[IFS_RX].packets,
|
||||
is->last_known[IFS_TX].bytes,
|
||||
is->last_known[IFS_TX].packets,
|
||||
is->active,
|
||||
is->net_dev,
|
||||
is->proc_ptr);
|
||||
res = kasprintf(GFP_ATOMIC, "iface_stat@null{}");
|
||||
else
|
||||
res = kasprintf(GFP_ATOMIC, "iface_stat@%p{"
|
||||
"list=list_head{...}, "
|
||||
"ifname=%s, "
|
||||
"total={rx={bytes=%llu, "
|
||||
"packets=%llu}, "
|
||||
"tx={bytes=%llu, "
|
||||
"packets=%llu}}, "
|
||||
"last_known_valid=%d, "
|
||||
"last_known={rx={bytes=%llu, "
|
||||
"packets=%llu}, "
|
||||
"tx={bytes=%llu, "
|
||||
"packets=%llu}}, "
|
||||
"active=%d, "
|
||||
"net_dev=%p, "
|
||||
"proc_ptr=%p, "
|
||||
"tag_stat_tree=rb_root{...}}",
|
||||
is,
|
||||
is->ifname,
|
||||
is->totals[IFS_RX].bytes,
|
||||
is->totals[IFS_RX].packets,
|
||||
is->totals[IFS_TX].bytes,
|
||||
is->totals[IFS_TX].packets,
|
||||
is->last_known_valid,
|
||||
is->last_known[IFS_RX].bytes,
|
||||
is->last_known[IFS_RX].packets,
|
||||
is->last_known[IFS_TX].bytes,
|
||||
is->last_known[IFS_TX].packets,
|
||||
is->active,
|
||||
is->net_dev,
|
||||
is->proc_ptr);
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
char *pp_sock_tag(struct sock_tag *st)
|
||||
|
|
@ -180,8 +219,11 @@ char *pp_sock_tag(struct sock_tag *st)
|
|||
char *tag_str;
|
||||
char *res;
|
||||
|
||||
if (!st)
|
||||
return kasprintf(GFP_ATOMIC, "sock_tag@null{}");
|
||||
if (!st) {
|
||||
res = kasprintf(GFP_ATOMIC, "sock_tag@null{}");
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
tag_str = pp_tag_t(&st->tag);
|
||||
res = kasprintf(GFP_ATOMIC, "sock_tag@%p{"
|
||||
"sock_node=rb_node{...}, "
|
||||
|
|
@ -190,6 +232,7 @@ char *pp_sock_tag(struct sock_tag *st)
|
|||
st, st->sk, st->socket, atomic_long_read(
|
||||
&st->socket->file->f_count),
|
||||
st->pid, tag_str);
|
||||
_bug_on_err_or_null(res);
|
||||
kfree(tag_str);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -199,13 +242,16 @@ char *pp_uid_tag_data(struct uid_tag_data *utd)
|
|||
char *res;
|
||||
|
||||
if (!utd)
|
||||
return kasprintf(GFP_ATOMIC, "uid_tag_data@null{}");
|
||||
res = kasprintf(GFP_ATOMIC, "uid_tag_data@%p{"
|
||||
"uid=%u, num_active_acct_tags=%d, "
|
||||
"tag_node_tree=rb_root{...}, "
|
||||
"proc_qtu_data_tree=rb_root{...}}",
|
||||
utd, utd->uid,
|
||||
utd->num_active_tags);
|
||||
res = kasprintf(GFP_ATOMIC, "uid_tag_data@null{}");
|
||||
else
|
||||
res = kasprintf(GFP_ATOMIC, "uid_tag_data@%p{"
|
||||
"uid=%u, num_active_acct_tags=%d, "
|
||||
"num_pqd=%d, "
|
||||
"tag_node_tree=rb_root{...}, "
|
||||
"proc_qtu_data_tree=rb_root{...}}",
|
||||
utd, utd->uid,
|
||||
utd->num_active_tags, utd->num_pqd);
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -214,8 +260,11 @@ char *pp_proc_qtu_data(struct proc_qtu_data *pqd)
|
|||
char *parent_tag_data_str;
|
||||
char *res;
|
||||
|
||||
if (!pqd)
|
||||
return kasprintf(GFP_ATOMIC, "proc_qtu_data@null{}");
|
||||
if (!pqd) {
|
||||
res = kasprintf(GFP_ATOMIC, "proc_qtu_data@null{}");
|
||||
_bug_on_err_or_null(res);
|
||||
return res;
|
||||
}
|
||||
parent_tag_data_str = pp_uid_tag_data(pqd->parent_tag_data);
|
||||
res = kasprintf(GFP_ATOMIC, "proc_qtu_data@%p{"
|
||||
"node=rb_node{...}, pid=%u, "
|
||||
|
|
@ -223,6 +272,7 @@ char *pp_proc_qtu_data(struct proc_qtu_data *pqd)
|
|||
"sock_tag_list=list_head{...}}",
|
||||
pqd, pqd->pid, parent_tag_data_str
|
||||
);
|
||||
_bug_on_err_or_null(res);
|
||||
kfree(parent_tag_data_str);
|
||||
return res;
|
||||
}
|
||||
|
|
@ -235,20 +285,29 @@ void prdebug_sock_tag_tree(int indent_level,
|
|||
struct sock_tag *sock_tag_entry;
|
||||
char *str;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
if (RB_EMPTY_ROOT(sock_tag_tree)) {
|
||||
str = "sock_tag_tree=rb_root{}";
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
return;
|
||||
}
|
||||
|
||||
str = "sock_tag_tree=rb_root{";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
indent_level++;
|
||||
for (node = rb_first(sock_tag_tree);
|
||||
node;
|
||||
node = rb_next(node)) {
|
||||
sock_tag_entry = rb_entry(node, struct sock_tag, sock_node);
|
||||
str = pp_sock_tag(sock_tag_entry);
|
||||
CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s,\n", indent_level*2, indent_level, str);
|
||||
kfree(str);
|
||||
}
|
||||
indent_level--;
|
||||
str = "}";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
}
|
||||
|
||||
void prdebug_sock_tag_list(int indent_level,
|
||||
|
|
@ -257,17 +316,26 @@ void prdebug_sock_tag_list(int indent_level,
|
|||
struct sock_tag *sock_tag_entry;
|
||||
char *str;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
if (list_empty(sock_tag_list)) {
|
||||
str = "sock_tag_list=list_head{}";
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
return;
|
||||
}
|
||||
|
||||
str = "sock_tag_list=list_head{";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
indent_level++;
|
||||
list_for_each_entry(sock_tag_entry, sock_tag_list, list) {
|
||||
str = pp_sock_tag(sock_tag_entry);
|
||||
CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s,\n", indent_level*2, indent_level, str);
|
||||
kfree(str);
|
||||
}
|
||||
indent_level--;
|
||||
str = "}";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
}
|
||||
|
||||
void prdebug_proc_qtu_data_tree(int indent_level,
|
||||
|
|
@ -277,8 +345,17 @@ void prdebug_proc_qtu_data_tree(int indent_level,
|
|||
struct rb_node *node;
|
||||
struct proc_qtu_data *proc_qtu_data_entry;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
if (RB_EMPTY_ROOT(proc_qtu_data_tree)) {
|
||||
str = "proc_qtu_data_tree=rb_root{}";
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
return;
|
||||
}
|
||||
|
||||
str = "proc_qtu_data_tree=rb_root{";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
indent_level++;
|
||||
for (node = rb_first(proc_qtu_data_tree);
|
||||
node;
|
||||
|
|
@ -287,7 +364,7 @@ void prdebug_proc_qtu_data_tree(int indent_level,
|
|||
struct proc_qtu_data,
|
||||
node);
|
||||
str = pp_proc_qtu_data(proc_qtu_data_entry);
|
||||
CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level,
|
||||
pr_debug("%*d: %s,\n", indent_level*2, indent_level,
|
||||
str);
|
||||
kfree(str);
|
||||
indent_level++;
|
||||
|
|
@ -298,7 +375,7 @@ void prdebug_proc_qtu_data_tree(int indent_level,
|
|||
}
|
||||
indent_level--;
|
||||
str = "}";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
}
|
||||
|
||||
void prdebug_tag_ref_tree(int indent_level, struct rb_root *tag_ref_tree)
|
||||
|
|
@ -307,8 +384,17 @@ void prdebug_tag_ref_tree(int indent_level, struct rb_root *tag_ref_tree)
|
|||
struct rb_node *node;
|
||||
struct tag_ref *tag_ref_entry;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
if (RB_EMPTY_ROOT(tag_ref_tree)) {
|
||||
str = "tag_ref_tree{}";
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
return;
|
||||
}
|
||||
|
||||
str = "tag_ref_tree{";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
indent_level++;
|
||||
for (node = rb_first(tag_ref_tree);
|
||||
node;
|
||||
|
|
@ -317,13 +403,13 @@ void prdebug_tag_ref_tree(int indent_level, struct rb_root *tag_ref_tree)
|
|||
struct tag_ref,
|
||||
tn.node);
|
||||
str = pp_tag_ref(tag_ref_entry);
|
||||
CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level,
|
||||
pr_debug("%*d: %s,\n", indent_level*2, indent_level,
|
||||
str);
|
||||
kfree(str);
|
||||
}
|
||||
indent_level--;
|
||||
str = "}";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
}
|
||||
|
||||
void prdebug_uid_tag_data_tree(int indent_level,
|
||||
|
|
@ -333,8 +419,17 @@ void prdebug_uid_tag_data_tree(int indent_level,
|
|||
struct rb_node *node;
|
||||
struct uid_tag_data *uid_tag_data_entry;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
if (RB_EMPTY_ROOT(uid_tag_data_tree)) {
|
||||
str = "uid_tag_data_tree=rb_root{}";
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
return;
|
||||
}
|
||||
|
||||
str = "uid_tag_data_tree=rb_root{";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
indent_level++;
|
||||
for (node = rb_first(uid_tag_data_tree);
|
||||
node;
|
||||
|
|
@ -342,7 +437,7 @@ void prdebug_uid_tag_data_tree(int indent_level,
|
|||
uid_tag_data_entry = rb_entry(node, struct uid_tag_data,
|
||||
node);
|
||||
str = pp_uid_tag_data(uid_tag_data_entry);
|
||||
CT_DEBUG("%*d: %s,\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s,\n", indent_level*2, indent_level, str);
|
||||
kfree(str);
|
||||
if (!RB_EMPTY_ROOT(&uid_tag_data_entry->tag_ref_tree)) {
|
||||
indent_level++;
|
||||
|
|
@ -353,7 +448,7 @@ void prdebug_uid_tag_data_tree(int indent_level,
|
|||
}
|
||||
indent_level--;
|
||||
str = "}";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
}
|
||||
|
||||
void prdebug_tag_stat_tree(int indent_level,
|
||||
|
|
@ -363,21 +458,30 @@ void prdebug_tag_stat_tree(int indent_level,
|
|||
struct rb_node *node;
|
||||
struct tag_stat *ts_entry;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
if (RB_EMPTY_ROOT(tag_stat_tree)) {
|
||||
str = "tag_stat_tree{}";
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
return;
|
||||
}
|
||||
|
||||
str = "tag_stat_tree{";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
indent_level++;
|
||||
for (node = rb_first(tag_stat_tree);
|
||||
node;
|
||||
node = rb_next(node)) {
|
||||
ts_entry = rb_entry(node, struct tag_stat, tn.node);
|
||||
str = pp_tag_stat(ts_entry);
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level,
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level,
|
||||
str);
|
||||
kfree(str);
|
||||
}
|
||||
indent_level--;
|
||||
str = "}";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
}
|
||||
|
||||
void prdebug_iface_stat_list(int indent_level,
|
||||
|
|
@ -386,12 +490,21 @@ void prdebug_iface_stat_list(int indent_level,
|
|||
char *str;
|
||||
struct iface_stat *iface_entry;
|
||||
|
||||
if (!unlikely(qtaguid_debug_mask & DDEBUG_MASK))
|
||||
return;
|
||||
|
||||
if (list_empty(iface_stat_list)) {
|
||||
str = "iface_stat_list=list_head{}";
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
return;
|
||||
}
|
||||
|
||||
str = "iface_stat_list=list_head{";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
indent_level++;
|
||||
list_for_each_entry(iface_entry, iface_stat_list, list) {
|
||||
str = pp_iface_stat(iface_entry);
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
kfree(str);
|
||||
|
||||
spin_lock_bh(&iface_entry->tag_stat_list_lock);
|
||||
|
|
@ -405,9 +518,10 @@ void prdebug_iface_stat_list(int indent_level,
|
|||
}
|
||||
indent_level--;
|
||||
str = "}";
|
||||
CT_DEBUG("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
pr_debug("%*d: %s\n", indent_level*2, indent_level, str);
|
||||
}
|
||||
|
||||
#endif /* ifdef DDEBUG */
|
||||
/*------------------------------------------*/
|
||||
static const char * const netdev_event_strings[] = {
|
||||
"netdev_unknown",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "xt_qtaguid_internal.h"
|
||||
|
||||
#ifdef DDEBUG
|
||||
|
||||
char *pp_tag_t(tag_t *tag);
|
||||
char *pp_data_counters(struct data_counters *dc, bool showValues);
|
||||
char *pp_tag_node(struct tag_node *tn);
|
||||
|
|
@ -37,6 +39,82 @@ void prdebug_tag_stat_tree(int indent_level,
|
|||
void prdebug_iface_stat_list(int indent_level,
|
||||
struct list_head *iface_stat_list);
|
||||
|
||||
#else
|
||||
|
||||
/*------------------------------------------*/
|
||||
static inline char *pp_tag_t(tag_t *tag)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_data_counters(struct data_counters *dc, bool showValues)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_tag_node(struct tag_node *tn)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_tag_ref(struct tag_ref *tr)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_tag_stat(struct tag_stat *ts)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_iface_stat(struct iface_stat *is)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_sock_tag(struct sock_tag *st)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_uid_tag_data(struct uid_tag_data *qtd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline char *pp_proc_qtu_data(struct proc_qtu_data *pqd)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*------------------------------------------*/
|
||||
static inline
|
||||
void prdebug_sock_tag_list(int indent_level,
|
||||
struct list_head *sock_tag_list)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void prdebug_sock_tag_tree(int indent_level,
|
||||
struct rb_root *sock_tag_tree)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void prdebug_proc_qtu_data_tree(int indent_level,
|
||||
struct rb_root *proc_qtu_data_tree)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void prdebug_tag_ref_tree(int indent_level, struct rb_root *tag_ref_tree)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void prdebug_uid_tag_data_tree(int indent_level,
|
||||
struct rb_root *uid_tag_data_tree)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void prdebug_tag_stat_tree(int indent_level,
|
||||
struct rb_root *tag_stat_tree)
|
||||
{
|
||||
}
|
||||
static inline
|
||||
void prdebug_iface_stat_list(int indent_level,
|
||||
struct list_head *iface_stat_list)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
/*------------------------------------------*/
|
||||
const char *netdev_evt_str(int netdev_event);
|
||||
#endif /* ifndef __XT_QTAGUID_PRINT_H__ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user