summaryrefslogtreecommitdiffstats
path: root/alsa-fix-substream-proc-status-read.patch
blob: 4d7ef08dbe6e4c31faf3ddf07f5f489178cc0c9b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
From: Takashi Iwai <tiwai@suse.de>
To: Chuck Ebbert <cebbert@redhat.com>
Cc: alsa-devel@alsa-project.org, linux-kernel@vger.kernel.org
Subject: Re: [alsa-devel] 2.6.36-rc2-git5: Oops in	snd_pcm_substream_proc_status_read()
Date: Thu, 02 Sep 2010 10:31:11 +0200

At Wed, 1 Sep 2010 04:19:24 -0400,
Chuck Ebbert wrote:
> 
> 
>  https://bugzilla.redhat.com/show_bug.cgi?id=628404
> 
> general protection fault: 0000 [#1] SMP 
> last sysfs file:
> /sys/devices/pci0000:00/0000:00:1b.0/sound/card0/pcmC0D0c/pcm_class
> CPU 1 
> Modules linked in: vfat fat fuse ebtable_nat ebtables ipt_MASQUERADE
> iptable_nat nf_nat bridge stp llc sunrpc cpufreq_ondemand acpi_cpufreq
> freq_table mperf ip6t_REJECT nf_conntrack_ipv6 xt_physdev ip6table_filter
> ip6_tables kvm_intel kvm uinput snd_hda_codec_conexant usblp arc4 ecb
> snd_hda_intel snd_hda_codec snd_hwdep snd_seq snd_seq_device iwlagn snd_pcm
> iwlcore thinkpad_acpi snd_timer snd i2c_i801 mac80211 soundcore microcode
> iTCO_wdt iTCO_vendor_support e1000e cfg80211 wmi snd_page_alloc rfkill ipv6
> usb_storage i915 drm_kms_helper drm i2c_algo_bit i2c_core video output [last
> unloaded: scsi_wait_scan]
> 
> Pid: 16071, comm: pulseaudio Not tainted 2.6.36-0.11.rc2.git5.fc15.x86_64 #1
> 74585FU/74585FU
> RIP: 0010:[<ffffffffa0296742>]  [<ffffffffa0296742>]
> snd_pcm_substream_proc_status_read+0x164/0x1ad [snd_pcm]
> RSP: 0018:ffff8801178c1b58  EFLAGS: 00010292
> RAX: 6b6b6b6b6b6b6b6b RBX: ffff88003d993bc8 RCX: 0000000000000000
> RDX: ffffffffa02a1996 RSI: ffffffffa02a1997 RDI: ffff88003d993bc8
> RBP: ffff8801178c1c18 R08: 0000000000000006 R09: 00000000fffffff7
> R10: ffff8800044ea048 R11: 0000000000000000 R12: ffff8801332d31b0
> R13: ffff88013438d488 R14: ffff88013438e050 R15: ffff880111131880
> FS:  00007fbccba77780(0000) GS:ffff880002e00000(0000) knlGS:0000000000000000
> CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
> CR2: 00007fbf324db008 CR3: 00000001157be000 CR4: 00000000000006e0
> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
> DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
> Process pulseaudio (pid: 16071, threadinfo ffff8801178c0000, task
> ffff880130f88000)
> Stack:
>  0000000000000003 0000000000005e84 000000002ee6c142 0000000000005e85  
> <0> 000000001624774a 0000000000000000 00000000000064b0 00000000000064b0
> <0> 00000000000064b0 00000000000064b0 0000000000000000 0000000000000000  
> Call Trace:  
>  [<ffffffffa020ac22>] snd_info_entry_open+0x307/0x389 [snd]
>  [<ffffffff81179034>] proc_reg_open+0xfa/0x17a
>  [<ffffffffa020a91b>] ? snd_info_entry_open+0x0/0x389 [snd]
>  [<ffffffffa0209fa7>] ? snd_info_entry_release+0x0/0xd8 [snd]
>  [<ffffffff81178f3a>] ? proc_reg_open+0x0/0x17a
>  [<ffffffff81128f1f>] __dentry_open+0x1c2/0x338
>  [<ffffffff81129da0>] nameidata_to_filp+0x3f/0x50
>  [<ffffffff81136200>] do_last+0x432/0x5af
>  [<ffffffff81246a75>] ? __raw_spin_lock_init+0x31/0x50
>  [<ffffffff811365ad>] do_filp_open+0x230/0x5e1
>  [<ffffffff810fac10>] ? might_fault+0x5c/0xac
>  [<ffffffff8114040b>] ? alloc_fd+0x3b/0x17c
>  [<ffffffff8107fc2a>] ? lock_release+0x19a/0x1a6
>  [<ffffffff8114053a>] ? alloc_fd+0x16a/0x17c
>  [<ffffffff81129e11>] do_sys_open+0x60/0xfc
>  [<ffffffff8149aca2>] ? trace_hardirqs_on_thunk+0x3a/0x3f
>  [<ffffffff81129ecd>] sys_open+0x20/0x22
>  [<ffffffff81009cb2>] system_call_fastpath+0x16/0x1b  
> Code: df 31 c0 e8 e6 40 f7 ff 48 c7 c6 90 19 2a a0 48 89 df 31 c0 e8 d5 40 f7
> ff 49 8b 84 24 f0 00 00 00 48 c7 c6 97 19 2a a0 48 89 df <48> 8b 50 08 31 c0 e8
> b8 40 f7 ff 49 8b 84 24 f8 00 00 00 48 c7 
> RIP  [<ffffffffa0296742>] snd_pcm_substream_proc_status_read+0x164/0x1ad
> [snd_pcm]
>  RSP <ffff8801178c1b58>
> ---[ end trace 96389f116dd90473 ]---
> 
> Faulting insn:
> 48 8b 50 08           mov    0x8(%rax),%rdx
> 
> RAX: 6b6b6b6b6b6b6b6b
> 
> sound/core/pcm.c:453:
> 
>    snd_iprintf(buffer, "hw_ptr : %ld\n", runtime->status->hw_ptr);
> 
> runtime = 0x6b6b6b6b6b6b6b6b
> 
> The code checks for NULL before using it, but this is a poison value.  

Looks like a race.
Could you check whether the patch below fixes the problem?


thanks,

Takashi

---
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 204af48..ac242a3 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -372,14 +372,17 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
 						  struct snd_info_buffer *buffer)
 {
 	struct snd_pcm_substream *substream = entry->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_pcm_runtime *runtime;
+
+	mutex_lock(&substream->pcm->open_mutex);
+	runtime = substream->runtime;
 	if (!runtime) {
 		snd_iprintf(buffer, "closed\n");
-		return;
+		goto unlock;
 	}
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 		snd_iprintf(buffer, "no setup\n");
-		return;
+		goto unlock;
 	}
 	snd_iprintf(buffer, "access: %s\n", snd_pcm_access_name(runtime->access));
 	snd_iprintf(buffer, "format: %s\n", snd_pcm_format_name(runtime->format));
@@ -398,20 +401,25 @@ static void snd_pcm_substream_proc_hw_params_read(struct snd_info_entry *entry,
 		snd_iprintf(buffer, "OSS period frames: %lu\n", (unsigned long)runtime->oss.period_frames);
 	}
 #endif
+ unlock:
+	mutex_unlock(&substream->pcm->open_mutex);
 }
 
 static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
 						  struct snd_info_buffer *buffer)
 {
 	struct snd_pcm_substream *substream = entry->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_pcm_runtime *runtime;
+
+	mutex_lock(&substream->pcm->open_mutex);
+	runtime = substream->runtime;
 	if (!runtime) {
 		snd_iprintf(buffer, "closed\n");
-		return;
+		goto unlock;
 	}
 	if (runtime->status->state == SNDRV_PCM_STATE_OPEN) {
 		snd_iprintf(buffer, "no setup\n");
-		return;
+		goto unlock;
 	}
 	snd_iprintf(buffer, "tstamp_mode: %s\n", snd_pcm_tstamp_mode_name(runtime->tstamp_mode));
 	snd_iprintf(buffer, "period_step: %u\n", runtime->period_step);
@@ -421,24 +429,29 @@ static void snd_pcm_substream_proc_sw_params_read(struct snd_info_entry *entry,
 	snd_iprintf(buffer, "silence_threshold: %lu\n", runtime->silence_threshold);
 	snd_iprintf(buffer, "silence_size: %lu\n", runtime->silence_size);
 	snd_iprintf(buffer, "boundary: %lu\n", runtime->boundary);
+ unlock:
+	mutex_unlock(&substream->pcm->open_mutex);
 }
 
 static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
 					       struct snd_info_buffer *buffer)
 {
 	struct snd_pcm_substream *substream = entry->private_data;
-	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_pcm_runtime *runtime;
 	struct snd_pcm_status status;
 	int err;
+
+	mutex_lock(&substream->pcm->open_mutex);
+	runtime = substream->runtime;
 	if (!runtime) {
 		snd_iprintf(buffer, "closed\n");
-		return;
+		goto unlock;
 	}
 	memset(&status, 0, sizeof(status));
 	err = snd_pcm_status(substream, &status);
 	if (err < 0) {
 		snd_iprintf(buffer, "error %d\n", err);
-		return;
+		goto unlock;
 	}
 	snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
 	snd_iprintf(buffer, "owner_pid   : %d\n", pid_vnr(substream->pid));
@@ -452,6 +465,8 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
 	snd_iprintf(buffer, "-----\n");
 	snd_iprintf(buffer, "hw_ptr      : %ld\n", runtime->status->hw_ptr);
 	snd_iprintf(buffer, "appl_ptr    : %ld\n", runtime->control->appl_ptr);
+ unlock:
+	mutex_unlock(&substream->pcm->open_mutex);
 }
 
 #ifdef CONFIG_SND_PCM_XRUN_DEBUG