mirror of
				https://github.com/alsa-project/alsa-lib.git
				synced 2025-11-03 09:01:52 -05:00 
			
		
		
		
	ctl: add dimension validator
Linux 4.7 or former have no validator of dimension information. This can causes an issue related to user-defined element set. For example, When calculated total members in multi-dimensional matrix is larger than actual capacity of snd_ctl_elem_value_t, processes to handle the element can cause buffer-over-run. For backward portability of this userspace library, this commit adds a validator of dimension information. When userspace applications give invalid dimension information to APIs to add element set, they receive -EINVAL. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
		
							parent
							
								
									3ef712844f
								
							
						
					
					
						commit
						025e451b83
					
				
					 1 changed files with 42 additions and 0 deletions
				
			
		| 
						 | 
					@ -91,6 +91,7 @@ I/O operations.
 | 
				
			||||||
#include <fcntl.h>
 | 
					#include <fcntl.h>
 | 
				
			||||||
#include <signal.h>
 | 
					#include <signal.h>
 | 
				
			||||||
#include <sys/poll.h>
 | 
					#include <sys/poll.h>
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include "control_local.h"
 | 
					#include "control_local.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -302,6 +303,32 @@ int snd_ctl_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info)
 | 
				
			||||||
	return ctl->ops->element_info(ctl, info);
 | 
						return ctl->ops->element_info(ctl, info);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool validate_element_member_dimension(snd_ctl_elem_info_t *info)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int members;
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (info->dimen.d[0] == 0)
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						members = 1;
 | 
				
			||||||
 | 
						for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) {
 | 
				
			||||||
 | 
							if (info->dimen.d[i] == 0)
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							members *= info->dimen.d[i];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (members > info->count)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) {
 | 
				
			||||||
 | 
							if (info->dimen.d[i] > 0)
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return members == info->count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * \brief Create and add some user-defined control elements of integer type.
 | 
					 * \brief Create and add some user-defined control elements of integer type.
 | 
				
			||||||
 * \param ctl A handle of backend module for control interface.
 | 
					 * \param ctl A handle of backend module for control interface.
 | 
				
			||||||
| 
						 | 
					@ -366,6 +393,9 @@ int snd_ctl_elem_add_integer_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
 | 
				
			||||||
	info->value.integer.max = max;
 | 
						info->value.integer.max = max;
 | 
				
			||||||
	info->value.integer.step = step;
 | 
						info->value.integer.step = step;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!validate_element_member_dimension(info))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = ctl->ops->element_add(ctl, info);
 | 
						err = ctl->ops->element_add(ctl, info);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					@ -451,6 +481,9 @@ int snd_ctl_elem_add_integer64_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
 | 
				
			||||||
	info->value.integer64.max = max;
 | 
						info->value.integer64.max = max;
 | 
				
			||||||
	info->value.integer64.step = step;
 | 
						info->value.integer64.step = step;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!validate_element_member_dimension(info))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = ctl->ops->element_add(ctl, info);
 | 
						err = ctl->ops->element_add(ctl, info);
 | 
				
			||||||
	if (err < 0)
 | 
						if (err < 0)
 | 
				
			||||||
		return err;
 | 
							return err;
 | 
				
			||||||
| 
						 | 
					@ -524,6 +557,9 @@ int snd_ctl_elem_add_boolean_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
 | 
				
			||||||
	info->value.integer.min = 0;
 | 
						info->value.integer.min = 0;
 | 
				
			||||||
	info->value.integer.max = 1;
 | 
						info->value.integer.max = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!validate_element_member_dimension(info))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ctl->ops->element_add(ctl, info);
 | 
						return ctl->ops->element_add(ctl, info);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -605,6 +641,9 @@ int snd_ctl_elem_add_enumerated_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
 | 
				
			||||||
		p += strlen(labels[i]) + 1;
 | 
							p += strlen(labels[i]) + 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!validate_element_member_dimension(info))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = ctl->ops->element_add(ctl, info);
 | 
						err = ctl->ops->element_add(ctl, info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(buf);
 | 
						free(buf);
 | 
				
			||||||
| 
						 | 
					@ -663,6 +702,9 @@ int snd_ctl_elem_add_bytes_set(snd_ctl_t *ctl, snd_ctl_elem_info_t *info,
 | 
				
			||||||
	info->owner = element_count;
 | 
						info->owner = element_count;
 | 
				
			||||||
	info->count = member_count;
 | 
						info->count = member_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!validate_element_member_dimension(info))
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ctl->ops->element_add(ctl, info);
 | 
						return ctl->ops->element_add(ctl, info);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue