From: Andi Kleen <andi@firstfloor.org>
To: srostedt@redhat.com, rostedt@goodmis.org, ak@linux.intel.com,
linux-kernel@vger.kernel.org, stable@kernel.org,
tim.bird@am.sony.com
Subject: [PATCH] [39/50] tracing: Fix bug when reading system filters on module
Date: Thu, 28 Jul 2011 16:44:44 -0700 (PDT) [thread overview]
Message-ID: <20110728234444.027402403FF@tassilo.jf.intel.com> (raw)
In-Reply-To: <20110728444.299940435@firstfloor.org>
2.6.35-longterm review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt <srostedt@redhat.com>
[ upstream commit e9dbfae53eeb9fc3d4bb7da3df87fa9875f5da02 ]
removal
The event system is freed when its nr_events is set to zero. This happens
when a module created an event system and then later the module is
removed. Modules may share systems, so the system is allocated when
it is created and freed when the modules are unloaded and all the
events under the system are removed (nr_events set to zero).
The problem arises when a task opened the "filter" file for the
system. If the module is unloaded and it removed the last event for
that system, the system structure is freed. If the task that opened
the filter file accesses the "filter" file after the system has
been freed, the system will access an invalid pointer.
By adding a ref_count, and using it to keep track of what
is using the event system, we can free it after all users
are finished with the event system.
Cc: <stable@kernel.org>
Reported-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Index: linux-2.6.35.y/kernel/trace/trace.h
===================================================================
--- linux-2.6.35.y.orig/kernel/trace/trace.h
+++ linux-2.6.35.y/kernel/trace/trace.h
@@ -731,6 +731,7 @@ struct event_subsystem {
struct dentry *entry;
struct event_filter *filter;
int nr_events;
+ int ref_count;
};
struct filter_pred;
Index: linux-2.6.35.y/kernel/trace/trace_events.c
===================================================================
--- linux-2.6.35.y.orig/kernel/trace/trace_events.c
+++ linux-2.6.35.y/kernel/trace/trace_events.c
@@ -182,6 +182,35 @@ static void ftrace_clear_events(void)
mutex_unlock(&event_mutex);
}
+static void __put_system(struct event_subsystem *system)
+{
+ struct event_filter *filter = system->filter;
+
+ WARN_ON_ONCE(system->ref_count == 0);
+ if (--system->ref_count)
+ return;
+
+ if (filter) {
+ kfree(filter->filter_string);
+ kfree(filter);
+ }
+ kfree(system->name);
+ kfree(system);
+}
+
+static void __get_system(struct event_subsystem *system)
+{
+ WARN_ON_ONCE(system->ref_count == 0);
+ system->ref_count++;
+}
+
+static void put_system(struct event_subsystem *system)
+{
+ mutex_lock(&event_mutex);
+ __put_system(system);
+ mutex_unlock(&event_mutex);
+}
+
/*
* __ftrace_set_clr_event(NULL, NULL, NULL, set) will set/unset all events.
*/
@@ -704,6 +733,47 @@ event_filter_write(struct file *filp, co
return cnt;
}
+static LIST_HEAD(event_subsystems);
+
+static int subsystem_open(struct inode *inode, struct file *filp)
+{
+ struct event_subsystem *system = NULL;
+ int ret;
+
+ /* Make sure the system still exists */
+ mutex_lock(&event_mutex);
+ list_for_each_entry(system, &event_subsystems, list) {
+ if (system == inode->i_private) {
+ /* Don't open systems with no events */
+ if (!system->nr_events) {
+ system = NULL;
+ break;
+ }
+ __get_system(system);
+ break;
+ }
+ }
+ mutex_unlock(&event_mutex);
+
+ if (system != inode->i_private)
+ return -ENODEV;
+
+ ret = tracing_open_generic(inode, filp);
+ if (ret < 0)
+ put_system(system);
+
+ return ret;
+}
+
+static int subsystem_release(struct inode *inode, struct file *file)
+{
+ struct event_subsystem *system = inode->i_private;
+
+ put_system(system);
+
+ return 0;
+}
+
static ssize_t
subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
loff_t *ppos)
@@ -836,9 +906,10 @@ static const struct file_operations ftra
};
static const struct file_operations ftrace_subsystem_filter_fops = {
- .open = tracing_open_generic,
+ .open = subsystem_open,
.read = subsystem_filter_read,
.write = subsystem_filter_write,
+ .release = subsystem_release,
};
static const struct file_operations ftrace_system_enable_fops = {
@@ -872,8 +943,6 @@ static struct dentry *event_trace_events
return d_events;
}
-static LIST_HEAD(event_subsystems);
-
static struct dentry *
event_subsystem_dir(const char *name, struct dentry *d_events)
{
@@ -883,6 +952,7 @@ event_subsystem_dir(const char *name, st
/* First see if we did not already create this dir */
list_for_each_entry(system, &event_subsystems, list) {
if (strcmp(system->name, name) == 0) {
+ __get_system(system);
system->nr_events++;
return system->entry;
}
@@ -905,6 +975,7 @@ event_subsystem_dir(const char *name, st
}
system->nr_events = 1;
+ system->ref_count = 1;
system->name = kstrdup(name, GFP_KERNEL);
if (!system->name) {
debugfs_remove(system->entry);
@@ -1050,16 +1121,9 @@ static void remove_subsystem_dir(const c
list_for_each_entry(system, &event_subsystems, list) {
if (strcmp(system->name, name) == 0) {
if (!--system->nr_events) {
- struct event_filter *filter = system->filter;
-
debugfs_remove_recursive(system->entry);
list_del(&system->list);
- if (filter) {
- kfree(filter->filter_string);
- kfree(filter);
- }
- kfree(system->name);
- kfree(system);
+ __put_system(system);
}
break;
}
Index: linux-2.6.35.y/kernel/trace/trace_events_filter.c
===================================================================
--- linux-2.6.35.y.orig/kernel/trace/trace_events_filter.c
+++ linux-2.6.35.y/kernel/trace/trace_events_filter.c
@@ -1340,6 +1340,12 @@ int apply_subsystem_event_filter(struct
if (err)
goto out_unlock;
+ /* Make sure the system still has events */
+ if (!system->nr_events) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+
if (!strcmp(strstrip(filter_string), "0")) {
filter_free_subsystem_preds(system);
remove_filter_string(system->filter);
next prev parent reply other threads:[~2011-07-28 23:44 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-07-28 23:44 [PATCH] [0/50] 2.6.35.14 longterm review Andi Kleen
2011-07-28 23:44 ` [PATCH] [1/50] x86: Make Dell Latitude E6420 use reboot=pci Andi Kleen
2011-07-28 23:44 ` [PATCH] [2/50] mm/futex: fix futex writes on archs with SW tracking of Andi Kleen
2011-07-28 23:44 ` [PATCH] [3/50] mm/backing-dev.c: reset bdi min_ratio in bdi_unregister() Andi Kleen
2011-07-28 23:44 ` [PATCH] [4/50] xtensa: prevent arbitrary read in ptrace Andi Kleen
2011-07-28 23:44 ` [PATCH] [5/50] ipc/sem.c: fix race with concurrent semtimedop() timeouts Andi Kleen
2011-07-28 23:44 ` [PATCH] [6/50] jme: Fix unmap error (Causing system freeze) Andi Kleen
2011-07-28 23:44 ` [PATCH] [7/50] fix crash in scsi_dispatch_cmd() Andi Kleen
2011-07-28 23:44 ` [PATCH] [8/50] mmc: Add PCI fixup quirks for Ricoh 1180:e823 reader Andi Kleen
2011-07-28 23:44 ` [PATCH] [9/50] mmc: Added quirks for Ricoh 1180:e823 lower base clock Andi Kleen
2011-07-29 0:27 ` matsumur
2011-07-29 0:37 ` Andi Kleen
2011-07-29 0:46 ` matsumur
2011-07-29 0:47 ` Chris Ball
2011-07-29 2:10 ` matsumur
2011-07-29 2:49 ` Chris Ball
2011-07-28 23:44 ` [PATCH] [10/50] Drop -Werror in perf Andi Kleen
2011-07-28 23:44 ` [PATCH] [11/50] kexec, x86: Fix incorrect jump back address if not Andi Kleen
2011-07-28 23:44 ` [PATCH] [12/50] USB: serial: add IDs for WinChipHead USB->RS232 adapter Andi Kleen
2011-07-28 23:44 ` [PATCH] [13/50] davinci: DM365 EVM: fix video input mux bits Andi Kleen
2011-07-28 23:44 ` [PATCH] [14/50] powerpc/pseries/hvconsole: Fix dropped console output Andi Kleen
2011-07-28 23:44 ` [PATCH] [15/50] hvc_console: Improve tty/console put_chars handling Andi Kleen
2011-07-28 23:44 ` [PATCH] [16/50] powerpc/kdump: Fix timeout in crash_kexec_wait_realmode Andi Kleen
2011-07-28 23:44 ` [PATCH] [17/50] si4713-i2c: avoid potential buffer overflow on si4713 Andi Kleen
2011-07-28 23:44 ` [PATCH] [18/50] hwmon: (max1111) Fix race condition causing NULL pointer Andi Kleen
2011-07-28 23:44 ` [PATCH] [19/50] hwmon: (asus_atk0110) Fix memory leak Andi Kleen
2011-07-28 23:44 ` [PATCH] [20/50] USB: OHCI: fix another regression for NVIDIA controllers Andi Kleen
2011-07-28 23:44 ` [PATCH] [21/50] firewire: cdev: prevent race between first get_info ioctl Andi Kleen
2011-07-28 23:44 ` [PATCH] [22/50] firewire: cdev: return -ENOTTY for unimplemented ioctls, not Andi Kleen
2011-07-28 23:44 ` [PATCH] [23/50] svcrpc: fix list-corrupting race on nfsd shutdown Andi Kleen
2011-07-28 23:44 ` [PATCH] [24/50] x86: Look for IA32_ENERGY_PERF_BIAS support Andi Kleen
2011-07-28 23:44 ` [PATCH] [25/50] x86, intel, power: Initialize MSR_IA32_ENERGY_PERF_BIAS Andi Kleen
2011-07-28 23:44 ` [PATCH] [26/50] SUNRPC: Fix use of static variable in rpcb_getport_async Andi Kleen
2011-07-28 23:44 ` [PATCH] [27/50] ARM: pxa/cm-x300: fix V3020 RTC functionality Andi Kleen
2011-07-28 23:44 ` [PATCH] [28/50] firewire: ohci: do not bind to Pinnacle cards, avert panic Andi Kleen
2011-07-28 23:44 ` [PATCH] [29/50] mm/nommu.c: fix remap_pfn_range() Andi Kleen
2011-07-28 23:44 ` [PATCH] [30/50] EHCI: only power off port if over-current is active Andi Kleen
2011-07-28 23:44 ` [PATCH] [31/50] mac80211: Restart STA timers only on associated state Andi Kleen
2011-07-28 23:44 ` [PATCH] [32/50] usb: musb: restore INDEX register in resume path Andi Kleen
2011-07-28 23:44 ` [PATCH] [33/50] SUNRPC: Fix a race between work-queue and rpc_killall_tasks Andi Kleen
2011-07-28 23:44 ` [PATCH] [34/50] bttv: fix s_tuner for radio Andi Kleen
2011-07-28 23:44 ` [PATCH] [35/50] pvrusb2: fix g/s_tuner support Andi Kleen
2011-07-28 23:44 ` [PATCH] [36/50] v4l2-ioctl.c: prefill tuner type for g_frequency and Andi Kleen
2011-07-28 23:44 ` [PATCH] [37/50] mac80211: fix TKIP replay vulnerability Andi Kleen
2011-07-28 23:44 ` [PATCH] [38/50] ASoC: ak4642: fixup snd_soc_update_bits mask for PW_MGMT2 Andi Kleen
2011-07-28 23:44 ` Andi Kleen [this message]
2011-07-28 23:44 ` [PATCH] [40/50] tracing: Have "enable" file use refcounts like the "filter" Andi Kleen
2011-07-28 23:44 ` [PATCH] [41/50] ARM: pxa: fix PGSR register address calculation Andi Kleen
2011-07-28 23:44 ` [PATCH] [42/50] iommu/amd: Don't use MSI address range for DMA addresses Andi Kleen
2011-07-28 23:44 ` [PATCH] [43/50] staging: r8192e_pci: Handle duplicate PCI ID 0x10ec:0x8192 Andi Kleen
2011-07-28 23:44 ` [PATCH] [44/50] staging: comedi: fix infoleak to userspace Andi Kleen
2011-07-28 23:44 ` [PATCH] [45/50] Staging: hv: netvsc: Fix a bug in accounting transmit slots Andi Kleen
2011-07-28 23:44 ` [PATCH] [46/50] ARM: 6989/1: perf: do not start the PMU when no events are Andi Kleen
2011-07-28 23:44 ` [PATCH] [47/50] ASoC: Ensure we delay long enough for WM8994 FLL to lock Andi Kleen
2011-07-28 23:44 ` [PATCH] [48/50] SERIAL: SC26xx: Fix link error Andi Kleen
2011-07-28 23:44 ` [PATCH] [49/50] x86, mtrr: lock stop machine during MTRR rendezvous sequence Andi Kleen
2011-07-28 23:44 ` [PATCH] [50/50] ipv6: add special mode forwarding=2 to send RS while Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20110728234444.027402403FF@tassilo.jf.intel.com \
--to=andi@firstfloor.org \
--cc=ak@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=srostedt@redhat.com \
--cc=stable@kernel.org \
--cc=tim.bird@am.sony.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome