Received: by 10.223.185.116 with SMTP id b49csp5895303wrg; Wed, 28 Feb 2018 00:04:14 -0800 (PST) X-Google-Smtp-Source: AG47ELtUMscdXtS0383NvO7rhoeNJ7eYiLyjYM2s556qyM2nGCEljL0PdLSSyzZYXA2fUN5fXf6u X-Received: by 10.98.57.215 with SMTP id u84mr3547386pfj.152.1519805054754; Wed, 28 Feb 2018 00:04:14 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1519805054; cv=none; d=google.com; s=arc-20160816; b=UrCHs5FObWeSO6aaBByxyWHo6ejLVr4IHg+PMDIaf9yeZCnU83gXvhD6BpL5+pbA07 rkr4srnVwliybNkvGIPoogXfr+9jtHiAvoO0l/CsygKIwOpGehya0oOK9TOyRY4SUmtI VrvJrQRRYZGaCMb1B6KnHGR+i73YBrUZwlslecyWzdmaopp3z/LVjJqtcFw0qORIn8nU 9aICL7O8nrIdmx+/hoh6uy8/4xltUAuRVta0r6aAhpZtO72uFBMlDsH2aTAZn7Q9a3WS Po8mXDurmsXWY8VYCKTi7f2EzJGnnR0JO1q2SJmPt9O33XIo8nwxnil2ktbj+t7hh23x /mnQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:references:in-reply-to:date :subject:cc:to:from:arc-authentication-results; bh=d+u71Mn5SCH5XJsKX9mWno3wE2Rn0vbninDiGTmAmrQ=; b=kV++bnpda3JCj2Xqky6lbzkOdQNE9SMxuWCeSGGciF8BUmuUV7dYO5NyIhTU1ppir1 f+lnv+ZOlhC0shANPb9QcrsLgHft0mQlLm17BzpqrxahIx8oabI1IYjoCAlPjbA1EH8M kC4yxdaSCjMu6RDwv5tHRW6RYqTMeEhQogndsx30O6t3RGA1386NJkwuUuMyRE490id8 g6KBHSSp4ujubUPSJlT6VaWWnppd+2kRHtqdYtDUstfb+NQnnyLwnB+Apt9r1LX/mlKX Ps9UgDeilhcxmh0h2WyYgagivW4wpIy9RWLLjRrFEV6q/MoEhllO5uSiGWYox7D+kjQ5 ujiQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e6-v6si906914plt.123.2018.02.28.00.03.49; Wed, 28 Feb 2018 00:04:14 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=ibm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752211AbeB1HwL (ORCPT + 99 others); Wed, 28 Feb 2018 02:52:11 -0500 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:49120 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752170AbeB1HwB (ORCPT ); Wed, 28 Feb 2018 02:52:01 -0500 Received: from pps.filterd (m0098416.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w1S7nfoY126863 for ; Wed, 28 Feb 2018 02:52:00 -0500 Received: from e06smtp14.uk.ibm.com (e06smtp14.uk.ibm.com [195.75.94.110]) by mx0b-001b2d01.pphosted.com with ESMTP id 2gdpa74ndk-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Wed, 28 Feb 2018 02:52:00 -0500 Received: from localhost by e06smtp14.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 28 Feb 2018 07:51:58 -0000 Received: from b06cxnps3075.portsmouth.uk.ibm.com (9.149.109.195) by e06smtp14.uk.ibm.com (192.168.101.144) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 28 Feb 2018 07:51:55 -0000 Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps3075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w1S7ptQr64946326; Wed, 28 Feb 2018 07:51:55 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 99684A4057; Wed, 28 Feb 2018 07:44:58 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 58A7CA4055; Wed, 28 Feb 2018 07:44:56 +0000 (GMT) Received: from bangoria.in.ibm.com (unknown [9.124.31.161]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTP; Wed, 28 Feb 2018 07:44:56 +0000 (GMT) From: Ravi Bangoria To: peterz@infradead.org, mingo@redhat.com, acme@kernel.org, alexander.shishkin@linux.intel.com, jolsa@redhat.com, namhyung@kernel.org, linux-kernel@vger.kernel.org, rostedt@goodmis.org, mhiramat@kernel.org, ananth@linux.vnet.ibm.com, naveen.n.rao@linux.vnet.ibm.com, srikar@linux.vnet.ibm.com, oleg@redhat.com Cc: Ravi Bangoria Subject: [RFC 4/4] trace_uprobe: Fix multiple update of same semaphores Date: Wed, 28 Feb 2018 13:23:45 +0530 X-Mailer: git-send-email 2.14.3 In-Reply-To: <20180228075345.674-1-ravi.bangoria@linux.vnet.ibm.com> References: <20180228075345.674-1-ravi.bangoria@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18022807-0016-0000-0000-0000052AAF5B X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18022807-0017-0000-0000-00002866DFA4 Message-Id: <20180228075345.674-5-ravi.bangoria@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2018-02-28_04:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=2 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1802280094 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org For tiny binaries/libraries, different mmap regions points to the same file portion. In such cases, we may increment semaphore multiple times. But while de-registration, semaphore will get decremented only once, leaving semaphore > 0 even if no one is tracing on that marker. Ensure increment and decrement happens in sync by keeping list of mms in trace_uprobe. Increment semaphore only if mm is not present in the list and decrement only if mm is present in the list. Example # echo "p:sdt_tick/loop2 /tmp/tick:0x6e4 *0x10036" > uprobe_events Before patch: # echo 1 > events/sdt_tick/loop2/enable # ./Workspace/sdt_prog/tick & # dd if=/proc//mem bs=1 count=1 skip=268566582 2>/dev/null | xxd 0000000: 02 . # echo 0 > events/sdt_tick/loop2/enable # dd if=/proc//mem bs=1 count=1 skip=268566582 2>/dev/null | xxd 0000000: 01 . After patch: # echo 1 > events/sdt_tick/loop2/enable # ./Workspace/sdt_prog/tick & # dd if=/proc//mem bs=1 count=1 skip=268566582 2>/dev/null | xxd 0000000: 01 . # echo 0 > events/sdt_tick/loop2/enable # dd if=/proc//mem bs=1 count=1 skip=268566582 2>/dev/null | xxd 0000000: 00 . Signed-off-by: Ravi Bangoria --- kernel/trace/trace_uprobe.c | 105 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 3 deletions(-) diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index d14aafc..3f1e8bd 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -49,6 +49,11 @@ struct trace_uprobe_filter { struct list_head perf_events; }; +struct sdt_mm_list { + struct mm_struct *mm; + struct sdt_mm_list *next; +}; + /* * uprobe event core functions */ @@ -60,6 +65,8 @@ struct trace_uprobe { char *filename; unsigned long offset; unsigned long sdt_offset; /* sdt semaphore offset */ + struct sdt_mm_list *sml; + struct rw_semaphore sml_rw_sem; unsigned long nhit; struct trace_probe tp; }; @@ -273,6 +280,7 @@ static inline bool is_ret_probe(struct trace_uprobe *tu) if (is_ret) tu->consumer.ret_handler = uretprobe_dispatcher; init_trace_uprobe_filter(&tu->filter); + init_rwsem(&tu->sml_rw_sem); return tu; error: @@ -953,6 +961,75 @@ static bool sdt_valid_vma(struct trace_uprobe *tu, struct vm_area_struct *vma) return 0; } +static bool sdt_check_mm_list(struct trace_uprobe *tu, struct mm_struct *mm) +{ + struct sdt_mm_list *tmp = tu->sml; + + if (!tu->sml || !mm) + return false; + + while (tmp) { + if (tmp->mm == mm) + return true; + tmp = tmp->next; + } + + return false; +} + +static void sdt_add_mm_list(struct trace_uprobe *tu, struct mm_struct *mm) +{ + struct sdt_mm_list *tmp; + + tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); + if (!tmp) { + pr_info("sdt_add_mm_list failed.\n"); + return; + } + tmp->mm = mm; + tmp->next = tu->sml; + tu->sml = tmp; +} + +static void sdt_del_mm_list(struct trace_uprobe *tu, struct mm_struct *mm) +{ + struct sdt_mm_list *prev, *curr; + + if (!tu->sml) + return; + + if (tu->sml->mm == mm) { + curr = tu->sml; + tu->sml = tu->sml->next; + kfree(curr); + return; + } + + prev = tu->sml; + curr = tu->sml->next; + while (curr) { + if (curr->mm == mm) { + prev->next = curr->next; + kfree(curr); + return; + } + prev = curr; + curr = curr->next; + } +} + +static void sdt_flush_mm_list(struct trace_uprobe *tu) +{ + struct sdt_mm_list *next, *curr = tu->sml; + + while (curr) { + next = curr->next; + kfree(curr); + curr = next; + } + tu->sml = NULL; +} + /* * TODO: Adding this defination in include/linux/uprobes.h throws * warnings about address_sapce. Adding it here for the time being. @@ -970,20 +1047,26 @@ static void sdt_increment_sem(struct trace_uprobe *tu) if (IS_ERR(info)) goto out; + down_write(&tu->sml_rw_sem); while (info) { down_write(&info->mm->mmap_sem); vma = sdt_find_vma(info->mm, tu); if (!vma) goto cont; + if (sdt_check_mm_list(tu, info->mm)) + goto cont; + vaddr = offset_to_vaddr(vma, tu->sdt_offset); - sdt_update_sem(info->mm, vaddr, 1); + if (!sdt_update_sem(info->mm, vaddr, 1)) + sdt_add_mm_list(tu, info->mm); cont: up_write(&info->mm->mmap_sem); mmput(info->mm); info = free_uprobe_map_info(info); } + up_write(&tu->sml_rw_sem); out: uprobe_end_dup_mmap(); @@ -1001,8 +1084,16 @@ void trace_uprobe_mmap_callback(struct vm_area_struct *vma) !trace_probe_is_enabled(&tu->tp)) continue; + down_write(&tu->sml_rw_sem); + if (sdt_check_mm_list(tu, vma->vm_mm)) + goto cont; + vaddr = offset_to_vaddr(vma, tu->sdt_offset); - sdt_update_sem(vma->vm_mm, vaddr, 1); + if (!sdt_update_sem(vma->vm_mm, vaddr, 1)) + sdt_add_mm_list(tu, vma->vm_mm); + +cont: + up_write(&tu->sml_rw_sem); } mutex_unlock(&uprobe_lock); } @@ -1017,7 +1108,11 @@ static void sdt_decrement_sem(struct trace_uprobe *tu) if (IS_ERR(info)) return; + down_write(&tu->sml_rw_sem); while (info) { + if (!sdt_check_mm_list(tu, info->mm)) + goto cont; + down_write(&info->mm->mmap_sem); vma = sdt_find_vma(info->mm, tu); if (vma) { @@ -1025,10 +1120,14 @@ static void sdt_decrement_sem(struct trace_uprobe *tu) sdt_update_sem(info->mm, vaddr, -1); } up_write(&info->mm->mmap_sem); - + sdt_del_mm_list(tu, info->mm); + +cont: mmput(info->mm); info = free_uprobe_map_info(info); } + sdt_flush_mm_list(tu); + up_write(&tu->sml_rw_sem); } typedef bool (*filter_func_t)(struct uprobe_consumer *self, -- 1.8.3.1