mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	pcm: direct plugins: do more safe IPC semaphore handling
As reported dead-lock, do local lock counting and invoke abort() when the lock counts do not match at close() time. Reported-by: <mateen abdulmateen.shaikh@gmail.com> Signed-off-by: Jaroslav Kysela <perex@perex.cz>
This commit is contained in:
		
							parent
							
								
									b6eb0f9bfd
								
							
						
					
					
						commit
						a6813c2d0e
					
				
					 4 changed files with 28 additions and 12 deletions
				
			
		| 
						 | 
					@ -122,6 +122,7 @@ struct snd_pcm_direct {
 | 
				
			||||||
	mode_t ipc_perm;		/* IPC socket permissions */
 | 
						mode_t ipc_perm;		/* IPC socket permissions */
 | 
				
			||||||
	int ipc_gid;			/* IPC socket gid */
 | 
						int ipc_gid;			/* IPC socket gid */
 | 
				
			||||||
	int semid;			/* IPC global semaphore identification */
 | 
						int semid;			/* IPC global semaphore identification */
 | 
				
			||||||
 | 
						int locked[DIRECT_IPC_SEMS];	/* local lock counter */
 | 
				
			||||||
	int shmid;			/* IPC global shared memory identification */
 | 
						int shmid;			/* IPC global shared memory identification */
 | 
				
			||||||
	snd_pcm_direct_share_t *shmptr;	/* pointer to shared memory area */
 | 
						snd_pcm_direct_share_t *shmptr;	/* pointer to shared memory area */
 | 
				
			||||||
	snd_pcm_t *spcm; 		/* slave PCM handle */
 | 
						snd_pcm_t *spcm; 		/* slave PCM handle */
 | 
				
			||||||
| 
						 | 
					@ -257,13 +258,26 @@ static inline int snd_pcm_direct_semaphore_discard(snd_pcm_direct_t *dmix)
 | 
				
			||||||
static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
 | 
					static inline int snd_pcm_direct_semaphore_down(snd_pcm_direct_t *dmix, int sem_num)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
 | 
						struct sembuf op[2] = { { sem_num, 0, 0 }, { sem_num, 1, SEM_UNDO } };
 | 
				
			||||||
	return semop(dmix->semid, op, 2);
 | 
						int err = semop(dmix->semid, op, 2);
 | 
				
			||||||
 | 
						if (err == 0) dmix->locked[sem_num]++;
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
 | 
					static inline int snd_pcm_direct_semaphore_up(snd_pcm_direct_t *dmix, int sem_num)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
 | 
						struct sembuf op = { sem_num, -1, SEM_UNDO | IPC_NOWAIT };
 | 
				
			||||||
	return semop(dmix->semid, &op, 1);
 | 
						int err = semop(dmix->semid, &op, 1);
 | 
				
			||||||
 | 
						if (err == 0) dmix->locked[sem_num]--;
 | 
				
			||||||
 | 
						return err;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int snd_pcm_direct_semaphore_final(snd_pcm_direct_t *dmix, int sem_num)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (dmix->locked[sem_num] != 1) {
 | 
				
			||||||
 | 
							assert(dmix->locked[sem_num] != 1);
 | 
				
			||||||
 | 
							abort();
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return snd_pcm_direct_semaphore_up(dmix, sem_num);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix);
 | 
					int snd_pcm_direct_shm_create_or_connect(snd_pcm_direct_t *dmix);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -781,9 +781,9 @@ static int snd_pcm_dmix_close(snd_pcm_t *pcm)
 | 
				
			||||||
 	shm_sum_discard(dmix);
 | 
					 	shm_sum_discard(dmix);
 | 
				
			||||||
	if (snd_pcm_direct_shm_discard(dmix)) {
 | 
						if (snd_pcm_direct_shm_discard(dmix)) {
 | 
				
			||||||
		if (snd_pcm_direct_semaphore_discard(dmix))
 | 
							if (snd_pcm_direct_semaphore_discard(dmix))
 | 
				
			||||||
			snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
 | 
								snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		snd_pcm_direct_semaphore_up(dmix, DIRECT_IPC_SEM_CLIENT);
 | 
							snd_pcm_direct_semaphore_final(dmix, DIRECT_IPC_SEM_CLIENT);
 | 
				
			||||||
	free(dmix->bindings);
 | 
						free(dmix->bindings);
 | 
				
			||||||
	pcm->private_data = NULL;
 | 
						pcm->private_data = NULL;
 | 
				
			||||||
	free(dmix);
 | 
						free(dmix);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -470,10 +470,11 @@ static int snd_pcm_dshare_close(snd_pcm_t *pcm)
 | 
				
			||||||
 		snd_pcm_direct_server_discard(dshare);
 | 
					 		snd_pcm_direct_server_discard(dshare);
 | 
				
			||||||
 	if (dshare->client)
 | 
					 	if (dshare->client)
 | 
				
			||||||
 		snd_pcm_direct_client_discard(dshare);
 | 
					 		snd_pcm_direct_client_discard(dshare);
 | 
				
			||||||
	if (snd_pcm_direct_shm_discard(dshare))
 | 
						if (snd_pcm_direct_shm_discard(dshare)) {
 | 
				
			||||||
		snd_pcm_direct_semaphore_discard(dshare);
 | 
							if (snd_pcm_direct_semaphore_discard(dshare))
 | 
				
			||||||
	else
 | 
								snd_pcm_direct_semaphore_final(dshare, DIRECT_IPC_SEM_CLIENT);
 | 
				
			||||||
		snd_pcm_direct_semaphore_up(dshare, DIRECT_IPC_SEM_CLIENT);
 | 
						} else
 | 
				
			||||||
 | 
							snd_pcm_direct_semaphore_final(dshare, DIRECT_IPC_SEM_CLIENT);
 | 
				
			||||||
	free(dshare->bindings);
 | 
						free(dshare->bindings);
 | 
				
			||||||
	pcm->private_data = NULL;
 | 
						pcm->private_data = NULL;
 | 
				
			||||||
	free(dshare);
 | 
						free(dshare);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -391,10 +391,11 @@ static int snd_pcm_dsnoop_close(snd_pcm_t *pcm)
 | 
				
			||||||
 		snd_pcm_direct_server_discard(dsnoop);
 | 
					 		snd_pcm_direct_server_discard(dsnoop);
 | 
				
			||||||
 	if (dsnoop->client)
 | 
					 	if (dsnoop->client)
 | 
				
			||||||
 		snd_pcm_direct_client_discard(dsnoop);
 | 
					 		snd_pcm_direct_client_discard(dsnoop);
 | 
				
			||||||
	if (snd_pcm_direct_shm_discard(dsnoop))
 | 
						if (snd_pcm_direct_shm_discard(dsnoop)) {
 | 
				
			||||||
		snd_pcm_direct_semaphore_discard(dsnoop);
 | 
							if (snd_pcm_direct_semaphore_discard(dsnoop))
 | 
				
			||||||
	else
 | 
								snd_pcm_direct_semaphore_final(dsnoop, DIRECT_IPC_SEM_CLIENT);
 | 
				
			||||||
		snd_pcm_direct_semaphore_up(dsnoop, DIRECT_IPC_SEM_CLIENT);
 | 
						} else
 | 
				
			||||||
 | 
							snd_pcm_direct_semaphore_final(dsnoop, DIRECT_IPC_SEM_CLIENT);
 | 
				
			||||||
	free(dsnoop->bindings);
 | 
						free(dsnoop->bindings);
 | 
				
			||||||
	pcm->private_data = NULL;
 | 
						pcm->private_data = NULL;
 | 
				
			||||||
	free(dsnoop);
 | 
						free(dsnoop);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue