fix the deadlock in xt_qtaguid when enable DDEBUG
When DDEBUG is enabled, the prdebug_full_state() function will try to recursively aquire the spinlock of sock_tag_list and causing deadlock. A check statement is added before it aquire the spinlock to differentiate the behavior depend on the caller of the function. Bug: 36559739 Test: Compile and run test under system/extra/test/iptables/ Change-Id: Ie3397fbaa207e14fe214d47aaf5e8ca1f4a712ee Signed-off-by: Chenbo Feng <fengc@google.com> Git-commit: 8cb8a69b83bd577b97e8247aec866e651c5b96f5 Git-repo: https://android.googlesource.com/kernel/common.git Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
This commit is contained in:
parent
3ee02277ca
commit
a8485c865e
|
@ -1794,8 +1794,11 @@ ret_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, ...)
|
||||
/*
|
||||
* This function is not in xt_qtaguid_print.c because of locks visibility.
|
||||
* The lock of sock_tag_list must be aquired before calling this function
|
||||
*/
|
||||
static void prdebug_full_state_locked(int indent_level, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *fmt_buff;
|
||||
|
@ -1816,16 +1819,12 @@ static void prdebug_full_state(int indent_level, const char *fmt, ...)
|
|||
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);
|
||||
|
@ -1834,7 +1833,7 @@ static void prdebug_full_state(int indent_level, const char *fmt, ...)
|
|||
pr_debug("qtaguid: %s(): }\n", __func__);
|
||||
}
|
||||
#else
|
||||
static void prdebug_full_state(int indent_level, const char *fmt, ...) {}
|
||||
static void prdebug_full_state_locked(int indent_level, const char *fmt, ...) {}
|
||||
#endif
|
||||
|
||||
struct proc_ctrl_print_info {
|
||||
|
@ -1957,8 +1956,11 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v)
|
|||
(u64)atomic64_read(&qtu_events.match_no_sk),
|
||||
(u64)atomic64_read(&qtu_events.match_no_sk_file));
|
||||
|
||||
/* Count the following as part of the last item_index */
|
||||
prdebug_full_state(0, "proc ctrl");
|
||||
/* Count the following as part of the last item_index. No need
|
||||
* to lock the sock_tag_list here since it is already locked when
|
||||
* starting the seq_file operation
|
||||
*/
|
||||
prdebug_full_state_locked(0, "proc ctrl");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2868,8 +2870,10 @@ 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__,
|
||||
spin_lock_bh(&sock_tag_list_lock);
|
||||
prdebug_full_state_locked(0, "%s(): pid=%u tgid=%u", __func__,
|
||||
current->pid, current->tgid);
|
||||
spin_unlock_bh(&sock_tag_list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue