@@ -774,6 +774,11 @@ static int snd_pcm_oss_period_size(struct snd_pcm_substream *substream,
774774
775775 if (oss_period_size < 16 )
776776 return - EINVAL ;
777+
778+ /* don't allocate too large period; 1MB period must be enough */
779+ if (oss_period_size > 1024 * 1024 )
780+ return - ENOMEM ;
781+
777782 runtime -> oss .period_bytes = oss_period_size ;
778783 runtime -> oss .period_frames = 1 ;
779784 runtime -> oss .periods = oss_periods ;
@@ -837,6 +842,17 @@ static void unlock_params(struct snd_pcm_runtime *runtime)
837842 mutex_unlock (& runtime -> oss .params_lock );
838843}
839844
845+ static void snd_pcm_oss_release_buffers (struct snd_pcm_substream * substream )
846+ {
847+ struct snd_pcm_runtime * runtime = substream -> runtime ;
848+
849+ kvfree (runtime -> oss .buffer );
850+ runtime -> oss .buffer = NULL ;
851+ #ifdef CONFIG_SND_PCM_OSS_PLUGINS
852+ snd_pcm_oss_plugin_clear (substream );
853+ #endif
854+ }
855+
840856/* call with params_lock held */
841857static int snd_pcm_oss_change_params_locked (struct snd_pcm_substream * substream )
842858{
@@ -967,12 +983,10 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
967983 snd_pcm_oss_plugin_clear (substream );
968984 if (!direct ) {
969985 /* add necessary plugins */
970- snd_pcm_oss_plugin_clear (substream );
971986 err = snd_pcm_plug_format_plugins (substream , params , sparams );
972987 if (err < 0 ) {
973988 pcm_dbg (substream -> pcm ,
974989 "snd_pcm_plug_format_plugins failed: %i\n" , err );
975- snd_pcm_oss_plugin_clear (substream );
976990 goto failure ;
977991 }
978992 if (runtime -> oss .plugin_first ) {
@@ -981,18 +995,15 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
981995 if (err < 0 ) {
982996 pcm_dbg (substream -> pcm ,
983997 "snd_pcm_plugin_build_io failed: %i\n" , err );
984- snd_pcm_oss_plugin_clear (substream );
985998 goto failure ;
986999 }
9871000 if (substream -> stream == SNDRV_PCM_STREAM_PLAYBACK ) {
9881001 err = snd_pcm_plugin_append (plugin );
9891002 } else {
9901003 err = snd_pcm_plugin_insert (plugin );
9911004 }
992- if (err < 0 ) {
993- snd_pcm_oss_plugin_clear (substream );
1005+ if (err < 0 )
9941006 goto failure ;
995- }
9961007 }
9971008 }
9981009#endif
@@ -1043,10 +1054,9 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
10431054 goto failure ;
10441055 }
10451056#endif
1046- oss_period_size *= oss_frame_size ;
1047-
1048- oss_buffer_size = oss_period_size * runtime -> oss .periods ;
1049- if (oss_buffer_size < 0 ) {
1057+ oss_period_size = array_size (oss_period_size , oss_frame_size );
1058+ oss_buffer_size = array_size (oss_period_size , runtime -> oss .periods );
1059+ if (oss_buffer_size <= 0 ) {
10501060 err = - EINVAL ;
10511061 goto failure ;
10521062 }
@@ -1082,6 +1092,8 @@ static int snd_pcm_oss_change_params_locked(struct snd_pcm_substream *substream)
10821092
10831093 err = 0 ;
10841094failure :
1095+ if (err )
1096+ snd_pcm_oss_release_buffers (substream );
10851097 kfree (sw_params );
10861098 kfree (params );
10871099 kfree (sparams );
@@ -2351,13 +2363,7 @@ static void snd_pcm_oss_look_for_setup(struct snd_pcm *pcm, int stream,
23512363
23522364static void snd_pcm_oss_release_substream (struct snd_pcm_substream * substream )
23532365{
2354- struct snd_pcm_runtime * runtime ;
2355- runtime = substream -> runtime ;
2356- kvfree (runtime -> oss .buffer );
2357- runtime -> oss .buffer = NULL ;
2358- #ifdef CONFIG_SND_PCM_OSS_PLUGINS
2359- snd_pcm_oss_plugin_clear (substream );
2360- #endif
2366+ snd_pcm_oss_release_buffers (substream );
23612367 substream -> oss .oss = 0 ;
23622368}
23632369
0 commit comments