Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: timer: Limit max instances per timer

Currently we allow unlimited number of timer instances, and it may
bring the system hogging way too much CPU when too many timer
instances are opened and processed concurrently. This may end up with
a soft-lockup report as triggered by syzkaller, especially when
hrtimer backend is deployed.

Since such insane number of instances aren't demanded by the normal
use case of ALSA sequencer and it merely opens a risk only for abuse,
this patch introduces the upper limit for the number of instances per
timer backend. As default, it's set to 1000, but for the fine-grained
timer like hrtimer, it's set to 100.

Reported-by: syzbot
Tested-by: Jérôme Glisse <jglisse@redhat.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+57 -13
+2
include/sound/timer.h
··· 90 90 struct list_head ack_list_head; 91 91 struct list_head sack_list_head; /* slow ack list head */ 92 92 struct tasklet_struct task_queue; 93 + int max_instances; /* upper limit of timer instances */ 94 + int num_instances; /* current number of timer instances */ 93 95 }; 94 96 95 97 struct snd_timer_instance {
+1
sound/core/hrtimer.c
··· 159 159 timer->hw = hrtimer_hw; 160 160 timer->hw.resolution = resolution; 161 161 timer->hw.ticks = NANO_SEC / resolution; 162 + timer->max_instances = 100; /* lower the limit */ 162 163 163 164 err = snd_timer_global_register(timer); 164 165 if (err < 0) {
+54 -13
sound/core/timer.c
··· 180 180 * 181 181 * call this with register_mutex down. 182 182 */ 183 - static void snd_timer_check_slave(struct snd_timer_instance *slave) 183 + static int snd_timer_check_slave(struct snd_timer_instance *slave) 184 184 { 185 185 struct snd_timer *timer; 186 186 struct snd_timer_instance *master; ··· 190 190 list_for_each_entry(master, &timer->open_list_head, open_list) { 191 191 if (slave->slave_class == master->slave_class && 192 192 slave->slave_id == master->slave_id) { 193 + if (master->timer->num_instances >= 194 + master->timer->max_instances) 195 + return -EBUSY; 193 196 list_move_tail(&slave->open_list, 194 197 &master->slave_list_head); 198 + master->timer->num_instances++; 195 199 spin_lock_irq(&slave_active_lock); 196 200 slave->master = master; 197 201 slave->timer = master->timer; 198 202 spin_unlock_irq(&slave_active_lock); 199 - return; 203 + return 0; 200 204 } 201 205 } 202 206 } 207 + return 0; 203 208 } 204 209 205 210 /* ··· 213 208 * 214 209 * call this with register_mutex down. 215 210 */ 216 - static void snd_timer_check_master(struct snd_timer_instance *master) 211 + static int snd_timer_check_master(struct snd_timer_instance *master) 217 212 { 218 213 struct snd_timer_instance *slave, *tmp; 219 214 ··· 221 216 list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) { 222 217 if (slave->slave_class == master->slave_class && 223 218 slave->slave_id == master->slave_id) { 219 + if (master->timer->num_instances >= 220 + master->timer->max_instances) 221 + return -EBUSY; 224 222 list_move_tail(&slave->open_list, &master->slave_list_head); 223 + master->timer->num_instances++; 225 224 spin_lock_irq(&slave_active_lock); 226 225 spin_lock(&master->timer->lock); 227 226 slave->master = master; ··· 237 228 spin_unlock_irq(&slave_active_lock); 238 229 } 239 230 } 231 + return 0; 240 232 } 233 + 234 + static int snd_timer_close_locked(struct snd_timer_instance *timeri); 241 235 242 236 /* 243 237 * open a timer instance ··· 252 240 { 253 241 struct snd_timer *timer; 254 242 struct snd_timer_instance *timeri = NULL; 243 + int err; 255 244 256 245 if (tid->dev_class == SNDRV_TIMER_CLASS_SLAVE) { 257 246 /* open a slave instance */ ··· 272 259 timeri->slave_id = tid->device; 273 260 timeri->flags |= SNDRV_TIMER_IFLG_SLAVE; 274 261 list_add_tail(&timeri->open_list, &snd_timer_slave_list); 275 - snd_timer_check_slave(timeri); 262 + err = snd_timer_check_slave(timeri); 263 + if (err < 0) { 264 + snd_timer_close_locked(timeri); 265 + timeri = NULL; 266 + } 276 267 mutex_unlock(&register_mutex); 277 268 *ti = timeri; 278 - return 0; 269 + return err; 279 270 } 280 271 281 272 /* open a master instance */ ··· 304 287 mutex_unlock(&register_mutex); 305 288 return -EBUSY; 306 289 } 290 + } 291 + if (timer->num_instances >= timer->max_instances) { 292 + mutex_unlock(&register_mutex); 293 + return -EBUSY; 307 294 } 308 295 timeri = snd_timer_instance_new(owner, timer); 309 296 if (!timeri) { ··· 335 314 } 336 315 337 316 list_add_tail(&timeri->open_list, &timer->open_list_head); 338 - snd_timer_check_master(timeri); 317 + timer->num_instances++; 318 + err = snd_timer_check_master(timeri); 319 + if (err < 0) { 320 + snd_timer_close_locked(timeri); 321 + timeri = NULL; 322 + } 339 323 mutex_unlock(&register_mutex); 340 324 *ti = timeri; 341 - return 0; 325 + return err; 342 326 } 343 327 EXPORT_SYMBOL(snd_timer_open); 344 328 345 329 /* 346 330 * close a timer instance 331 + * call this with register_mutex down. 347 332 */ 348 - int snd_timer_close(struct snd_timer_instance *timeri) 333 + static int snd_timer_close_locked(struct snd_timer_instance *timeri) 349 334 { 350 335 struct snd_timer *timer = NULL; 351 336 struct snd_timer_instance *slave, *tmp; 352 337 353 - if (snd_BUG_ON(!timeri)) 354 - return -ENXIO; 355 - 356 - mutex_lock(&register_mutex); 357 338 list_del(&timeri->open_list); 358 339 359 340 /* force to stop the timer */ ··· 363 340 364 341 timer = timeri->timer; 365 342 if (timer) { 343 + timer->num_instances--; 366 344 /* wait, until the active callback is finished */ 367 345 spin_lock_irq(&timer->lock); 368 346 while (timeri->flags & SNDRV_TIMER_IFLG_CALLBACK) { ··· 379 355 list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, 380 356 open_list) { 381 357 list_move_tail(&slave->open_list, &snd_timer_slave_list); 358 + timer->num_instances--; 382 359 slave->master = NULL; 383 360 slave->timer = NULL; 384 361 list_del_init(&slave->ack_list); ··· 407 382 module_put(timer->module); 408 383 } 409 384 410 - mutex_unlock(&register_mutex); 411 385 return 0; 386 + } 387 + 388 + /* 389 + * close a timer instance 390 + */ 391 + int snd_timer_close(struct snd_timer_instance *timeri) 392 + { 393 + int err; 394 + 395 + if (snd_BUG_ON(!timeri)) 396 + return -ENXIO; 397 + 398 + mutex_lock(&register_mutex); 399 + err = snd_timer_close_locked(timeri); 400 + mutex_unlock(&register_mutex); 401 + return err; 412 402 } 413 403 EXPORT_SYMBOL(snd_timer_close); 414 404 ··· 896 856 spin_lock_init(&timer->lock); 897 857 tasklet_init(&timer->task_queue, snd_timer_tasklet, 898 858 (unsigned long)timer); 859 + timer->max_instances = 1000; /* default limit per timer */ 899 860 if (card != NULL) { 900 861 timer->module = card->module; 901 862 err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops);