Re: [PATCH] HID: core: replace the collection tree pointers with indices

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2019-01-09 at 13:50 +1000, Peter Hutterer wrote:
> Introduced in c53431eb696f3c64c12c00afb81048af54b61532
> "HID: core: store the collections as a basic tree".
> 
> Previously, the pointer to the parent collection was stored. If a
> device
> exceeds 16 collections (HID_DEFAULT_NUM_COLLECTIONS), the array to
> store
> the collections is reallocated, the pointer to the parent collection
> becomes
> invalid.
> 
> Replace the pointers with an index-based lookup into the collections
> array.
> 
> Reported-by: Pandruvada, Srinivas <srinivas.pandruvada@xxxxxxxxx>
> Signed-off-by: Peter Hutterer <peter.hutterer@xxxxxxxxx>
Added Kyle to this email, who is testing this change.

Thanks,
Srinivas
> ---
> I have a test locally for hid-tools now but it relies on the kernel
> crashing, so it's going to generate false positives. I verified the
> test
> with printks though.
> 
>  drivers/hid/hid-core.c | 32 +++++++++++++++++++++-----------
>  include/linux/hid.h    |  4 ++--
>  2 files changed, 23 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
> index f41d5fe51abe..f9093dedf647 100644
> --- a/drivers/hid/hid-core.c
> +++ b/drivers/hid/hid-core.c
> @@ -125,6 +125,7 @@ static int open_collection(struct hid_parser
> *parser, unsigned type)
>  {
>  	struct hid_collection *collection;
>  	unsigned usage;
> +	int collection_index;
>  
>  	usage = parser->local.usage[0];
>  
> @@ -167,13 +168,13 @@ static int open_collection(struct hid_parser
> *parser, unsigned type)
>  	parser->collection_stack[parser->collection_stack_ptr++] =
>  		parser->device->maxcollection;
>  
> -	collection = parser->device->collection +
> -		parser->device->maxcollection++;
> +	collection_index = parser->device->maxcollection++;
> +	collection = parser->device->collection + collection_index;
>  	collection->type = type;
>  	collection->usage = usage;
>  	collection->level = parser->collection_stack_ptr - 1;
> -	collection->parent = parser->active_collection;
> -	parser->active_collection = collection;
> +	collection->parent_idx = parser->active_collection_idx;
> +	parser->active_collection_idx = collection_index;
>  
>  	if (type == HID_COLLECTION_APPLICATION)
>  		parser->device->maxapplication++;
> @@ -192,8 +193,13 @@ static int close_collection(struct hid_parser
> *parser)
>  		return -EINVAL;
>  	}
>  	parser->collection_stack_ptr--;
> -	if (parser->active_collection)
> -		parser->active_collection = parser->active_collection-
> >parent;
> +	if (parser->active_collection_idx != -1) {
> +		struct hid_device *device = parser->device;
> +		struct hid_collection *c;
> +
> +		c = &device->collection[parser->active_collection_idx];
> +		parser->active_collection_idx = c->parent_idx;
> +	}
>  	return 0;
>  }
>  
> @@ -819,6 +825,7 @@ static int hid_scan_report(struct hid_device
> *hid)
>  		return -ENOMEM;
>  
>  	parser->device = hid;
> +	parser->active_collection_idx = -1;
>  	hid->group = HID_GROUP_GENERIC;
>  
>  	/*
> @@ -1006,10 +1013,12 @@ static void
> hid_apply_multiplier_to_field(struct hid_device *hid,
>  		usage = &field->usage[i];
>  
>  		collection = &hid->collection[usage->collection_index];
> -		while (collection && collection !=
> multiplier_collection)
> -			collection = collection->parent;
> +		while (collection->parent_idx != -1 &&
> +		       collection != multiplier_collection)
> +			collection = &hid->collection[collection-
> >parent_idx];
>  
> -		if (collection || multiplier_collection == NULL)
> +		if (collection->parent_idx != -1 ||
> +		    multiplier_collection == NULL)
>  			usage->resolution_multiplier =
> effective_multiplier;
>  
>  	}
> @@ -1044,9 +1053,9 @@ static void hid_apply_multiplier(struct
> hid_device *hid,
>  	 * applicable fields later.
>  	 */
>  	multiplier_collection = &hid->collection[multiplier->usage-
> >collection_index];
> -	while (multiplier_collection &&
> +	while (multiplier_collection->parent_idx != -1 &&
>  	       multiplier_collection->type != HID_COLLECTION_LOGICAL)
> -		multiplier_collection = multiplier_collection->parent;
> +		multiplier_collection = &hid-
> >collection[multiplier_collection->parent_idx];
>  
>  	effective_multiplier = hid_calculate_multiplier(hid,
> multiplier);
>  
> @@ -1170,6 +1179,7 @@ int hid_open_report(struct hid_device *device)
>  	}
>  
>  	parser->device = device;
> +	parser->active_collection_idx = -1;
>  
>  	end = start + size;
>  
> diff --git a/include/linux/hid.h b/include/linux/hid.h
> index 93db548f8761..554e82d812da 100644
> --- a/include/linux/hid.h
> +++ b/include/linux/hid.h
> @@ -429,7 +429,7 @@ struct hid_local {
>   */
>  
>  struct hid_collection {
> -	struct hid_collection *parent;
> +	int parent_idx; /* device->collection */
>  	unsigned type;
>  	unsigned usage;
>  	unsigned level;
> @@ -657,7 +657,7 @@ struct hid_parser {
>  	unsigned int         *collection_stack;
>  	unsigned int          collection_stack_ptr;
>  	unsigned int          collection_stack_size;
> -	struct hid_collection *active_collection;
> +	int                   active_collection_idx; /* device-
> >collection */
>  	struct hid_device    *device;
>  	unsigned int          scan_flags;
>  };

Attachment: smime.p7s
Description: S/MIME cryptographic signature


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux