ObjectCreateHashSequence(
			 TPMI_ALG_HASH    hashAlg,       // IN: hash algorithm
			 TPM2B_AUTH      *auth,          // IN: authValue
			 TPMI_DH_OBJECT  *newHandle      // OUT: sequence object handle
			 )
{
    HASH_OBJECT         *hashObject = AllocateSequenceSlot(newHandle, auth);
    // See if slot allocated
    if(hashObject == NULL)
	return TPM_RC_OBJECT_MEMORY;
    // Set hash sequence bit
    hashObject->attributes.hashSeq = SET;
    // Start hash for hash sequence
    CryptHashStart(&hashObject->state.hashState[0], hashAlg);
    return TPM_RC_SUCCESS;
}


ObjectCapGetTransientAvail(
			   void
			   )
{
    UINT32      i;
    UINT32      num = 0;
    // Iterate object slot to get the number of unoccupied slots
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
	{
	    if(s_objects[i].attributes.occupied == FALSE) num++;
	}
    return num;
}

tpm2: Initialize a whole OBJECT before using it

Initialize a whole OBJECT before using it. This is necessary since
an OBJECT may also be used as a HASH_OBJECT via the ANY_OBJECT
union and that HASH_OBJECT can leave bad size inidicators in TPM2B
buffer in the OBJECT. To get rid of this problem we reset the whole
OBJECT to 0 before using it. This is as if the memory for the
OBJECT was just initialized.

Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>


ObjectContextLoad(
		  ANY_OBJECT_BUFFER   *object,        // IN: pointer to object structure in saved
		  //     context
		  TPMI_DH_OBJECT      *handle         // OUT: object handle
		  )
{
    OBJECT      *newObject = ObjectAllocateSlot(handle);
    // Try to allocate a slot for new object
    if(newObject != NULL)
	{
	    // Copy the first part of the object
	    MemoryCopy(newObject, object, offsetof(HASH_OBJECT, state));
	    // See if this is a sequence object
	    if(ObjectIsSequence(newObject))
		{
		    // If this is a sequence object, import the data
		    SequenceDataImport((HASH_OBJECT *)newObject,
				       (HASH_OBJECT_BUFFER *)object);
		}
	    else
		{
		    // Copy input object data to internal structure
		    MemoryCopy(newObject, object, sizeof(OBJECT));
		}
	}
    return newObject;
}


ObjectAllocateSlot(
		   TPMI_DH_OBJECT  *handle        // OUT: handle of allocated object
		   )
{
    OBJECT          *object = FindEmptyObjectSlot(handle);
    if(object != NULL)
	{
	    // if found, mark as occupied
	    ObjectSetInUse(object);
	}
    return object;
}


ObjectGetPublicAttributes(
			  TPM_HANDLE       handle
			  )
{
    return HandleToObject(handle)->publicArea.objectAttributes;
}


ObjectSetLoadedAttributes(
			  OBJECT          *object,        // IN: object attributes to finalize
			  TPM_HANDLE       parentHandle   // IN: the parent handle
			  )
{
    OBJECT              *parent = HandleToObject(parentHandle);
    TPMA_OBJECT          objectAttributes = object->publicArea.objectAttributes;
    //
    // Copy the stClear attribute from the public area. This could be overwritten
    // if the parent has stClear SET
    object->attributes.stClear =
	IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear);
    // If parent handle is a permanent handle, it is a primary (unless it is NULL
    if(parent == NULL)
	{
	    object->attributes.primary = SET;
	    switch(parentHandle)
		{
		  case TPM_RH_ENDORSEMENT:
		    object->attributes.epsHierarchy = SET;
		    break;
		  case TPM_RH_OWNER:
		    object->attributes.spsHierarchy = SET;
		    break;
		  case TPM_RH_PLATFORM:
		    object->attributes.ppsHierarchy = SET;
		    break;
		  default:
		    // Treat the temporary attribute as a hierarchy
		    object->attributes.temporary = SET;
		    object->attributes.primary = CLEAR;
		    break;
		}
	}
    else
	{
	    // is this a stClear object
	    object->attributes.stClear =
		(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, stClear)
		 || (parent->attributes.stClear == SET));
	    object->attributes.epsHierarchy = parent->attributes.epsHierarchy;
	    object->attributes.spsHierarchy = parent->attributes.spsHierarchy;
	    object->attributes.ppsHierarchy = parent->attributes.ppsHierarchy;
	    // An object is temporary if its parent is temporary or if the object
	    // is external
	    object->attributes.temporary = parent->attributes.temporary
					   || object->attributes.external;
	}
    // If this is an external object, set the QN == name but don't SET other
    // key properties ('parent' or 'derived')
    if(object->attributes.external)
	object->qualifiedName = object->name;
    else
	{
	    // check attributes for different types of parents
	    if(IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, restricted)
	       && !object->attributes.publicOnly
	       && IS_ATTRIBUTE(objectAttributes, TPMA_OBJECT, decrypt)
	       && object->publicArea.nameAlg != TPM_ALG_NULL)
		{
		    // This is a parent. If it is not a KEYEDHASH, it is an ordinary parent.
		    // Otherwise, it is a derivation parent.
		    if(object->publicArea.type == TPM_ALG_KEYEDHASH)
			object->attributes.derivation = SET;
		    else
			object->attributes.isParent = SET;
		}
	    ComputeQualifiedName(parentHandle, object->publicArea.nameAlg,
				 &object->name, &object->qualifiedName);
	}
    // Set slot occupied
    ObjectSetInUse(object);
    return;
}


ObjectCleanupEvict(
		   void
		   )
{
    UINT32      i;
    // This has to be iterated because a command may have two handles
    // and they may both be persistent.
    // This could be made to be more efficient so that a search is not needed.
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
	{
	    // If an object is a temporary evict object, flush it from slot
	    OBJECT      *object = &s_objects[i];
	    if(object->attributes.evict == SET)
		ObjectFlush(object);
	}
    return;
}


FlushObject(
	    TPMI_DH_OBJECT   handle         // IN: handle to be freed
	    )
{
    UINT32      index = handle - TRANSIENT_FIRST;
    pAssert(index < MAX_LOADED_OBJECTS);
    // Clear all the object attributes
    MemorySet((BYTE*)&(s_objects[index].attributes),
	      0, sizeof(OBJECT_ATTRIBUTES));
    return;
}


ObjectIsStorage(
		TPMI_DH_OBJECT   handle         // IN: object handle
		)
{
    OBJECT           *object = HandleToObject(handle);
    TPMT_PUBLIC      *publicArea = ((object != NULL) ? &object->publicArea : NULL);
    //
    return (publicArea != NULL
	    && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, restricted)
	    && IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, decrypt)
	    && !IS_ATTRIBUTE(publicArea->objectAttributes, TPMA_OBJECT, sign)
	    && (object->publicArea.type == ALG_RSA_VALUE
		|| object->publicArea.type == ALG_ECC_VALUE));
}


ObjectGetNameAlg(
		 OBJECT          *object         // IN: handle of the object
		 )
{
    return object->publicArea.nameAlg;
}


ObjectLoad(
	   OBJECT          *object,        // IN: pointer to object slot
	   //     object
	   OBJECT          *parent,        // IN: (optional) the parent object
	   TPMT_PUBLIC     *publicArea,    // IN: public area to be installed in the object
	   TPMT_SENSITIVE  *sensitive,     // IN: (optional) sensitive area to be
	   //      installed in the object
	   TPM_RC           blamePublic,   // IN: parameter number to associate with the
	   //     publicArea errors
	   TPM_RC           blameSensitive,// IN: parameter number to associate with the
	   //     sensitive area errors
	   TPM2B_NAME      *name           // IN: (optional)
	   )
{
    TPM_RC           result = TPM_RC_SUCCESS;
    BOOL             doCheck;
    //
    // Do validations of public area object descriptions
    // Is this public only or a no-name object?
    if(sensitive == NULL || publicArea->nameAlg == TPM_ALG_NULL)
	{
	    // Need to have schemes checked so that we do the right thing with the
	    // public key.
	    result = SchemeChecks(NULL, publicArea);
	}
    else
	{
	    // For any sensitive area, make sure that the seedSize is no larger than the
	    // digest size of nameAlg
	    if(sensitive->seedValue.t.size
	       > CryptHashGetDigestSize(publicArea->nameAlg))
		return TPM_RCS_KEY_SIZE + blameSensitive;
	    // Check attributes and schemes for consistency
	    result = PublicAttributesValidation(parent, publicArea);
	}
    if(result != TPM_RC_SUCCESS)
	return RcSafeAddToResult(result, blamePublic);
    // If object == NULL, then this is am import. For import, load is not called
    // unless the parent is fixedTPM.
    if(object == NULL)
	doCheck = TRUE;// //
    // If the parent is not NULL, then this is an ordinary load and we only check
    // if the parent is not fixedTPM
    else if(parent != NULL)
	doCheck = !IS_ATTRIBUTE(parent->publicArea.objectAttributes,
				TPMA_OBJECT, fixedTPM);
    else
	// This is a loadExternal. Check everything.
	// Note: the check functions will filter things based on the name algorithm
	// and whether or not both parts are loaded.
	doCheck = TRUE;
    // Note: the parent will be NULL if this is a load external. CryptValidateKeys()
    // will only check the parts that need to be checked based on the settings
    // of publicOnly and nameAlg.
    // Note: For an RSA key, the keys sizes are checked but the binding is not
    // checked.
    if(doCheck)
	{
	    // Do the cryptographic key validation
	    result = CryptValidateKeys(publicArea, sensitive, blamePublic,
				       blameSensitive);
	}
    // If this is an import, we are done
    if(object == NULL || result != TPM_RC_SUCCESS)
	return result;
    // Set the name, if one was provided
    if(name != NULL)
	object->name = *name;
    else
	object->name.t.size = 0;
    // Initialize public
    object->publicArea = *publicArea;
    // If there is a sensitive area, load it
    if(sensitive == NULL)
	object->attributes.publicOnly = SET;
    else
	{
	    object->sensitive = *sensitive;
#if ALG_RSA
	    // If this is an RSA key that is not a parent, complete the load by
	    // computing the private exponent.
	    if(publicArea->type == ALG_RSA_VALUE)
		result = CryptRsaLoadPrivateExponent(object);
#endif
	}
    return result;
}


ObjectGetProperties(
		    TPM_HANDLE       handle
		    )
{
    return HandleToObject(handle)->attributes;
}


ObjectCapGetLoaded(
		   TPMI_DH_OBJECT   handle,        // IN: start handle
		   UINT32           count,         // IN: count of returned handles
		   TPML_HANDLE     *handleList     // OUT: list of handle
		   )
{
    TPMI_YES_NO          more = NO;
    UINT32               i;
    pAssert(HandleGetType(handle) == TPM_HT_TRANSIENT);
    // Initialize output handle list
    handleList->count = 0;
    // The maximum count of handles we may return is MAX_CAP_HANDLES
    if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
    // Iterate object slots to get loaded object handles
    for(i = handle - TRANSIENT_FIRST; i < MAX_LOADED_OBJECTS; i++)
	{
	    if(s_objects[i].attributes.occupied == TRUE)
		{
		    // A valid transient object can not be the copy of a persistent object
		    pAssert(s_objects[i].attributes.evict == CLEAR);
		    if(handleList->count < count)
			{
			    // If we have not filled up the return list, add this object
			    // handle to it
			    handleList->handle[handleList->count] = i + TRANSIENT_FIRST;
			    handleList->count++;
			}
		    else
			{
			    // If the return list is full but we still have loaded object
			    // available, report this and stop iterating
			    more = YES;
			    break;
			}
		}
	}
    return more;
}


ObjectStartup(
	      void
	      )
{
    UINT32      i;
    // object slots initialization
    for(i = 0; i < MAX_LOADED_OBJECTS; i++)
	{
	    //Set the slot to not occupied
	    ObjectFlush(&s_objects[i]);
	}
    return;
}


AllocateSequenceSlot(
		     TPM_HANDLE      *newHandle,     // OUT: receives the allocated handle
		     TPM2B_AUTH      *auth           // IN: the authValue for the slot
		     )
{
    HASH_OBJECT      *object = (HASH_OBJECT *)ObjectAllocateSlot(newHandle);
    //
    // Validate that the proper location of the hash state data relative to the
    // object state data. It would be good if this could have been done at compile
    // time but it can't so do it in something that can be removed after debug.
    cAssert(offsetof(HASH_OBJECT, auth) == offsetof(OBJECT, publicArea.authPolicy));
    if(object != NULL)
	{
	    // Set the common values that a sequence object shares with an ordinary object
	    // First, clear all attributes
	    MemorySet(&object->objectAttributes, 0, sizeof(TPMA_OBJECT));
	    // The type is TPM_ALG_NULL
	    object->type = TPM_ALG_NULL;
	    // This has no name algorithm and the name is the Empty Buffer
	    object->nameAlg = TPM_ALG_NULL;
	    // A sequence object is considered to be in the NULL hierarchy so it should
	    // be marked as temporary so that it can't be persisted
	    object->attributes.temporary = SET;
	    // A sequence object is DA exempt.
	    SET_ATTRIBUTE(object->objectAttributes, TPMA_OBJECT, noDA);
	    // Copy the authorization value
	    if(auth != NULL)
		object->auth = *auth;
	    else
		object->auth.t.size = 0;
	}
    return object;
}


IsObjectPresent(
		TPMI_DH_OBJECT   handle         // IN: handle to be checked
		)
{
    UINT32          slotIndex = handle - TRANSIENT_FIRST;
    // Since the handle is just an index into the array that is zero based, any
    // handle value outsize of the range of:
    //    TRANSIENT_FIRST -- (TRANSIENT_FIRST + MAX_LOADED_OBJECT - 1)
    // will now be greater than or equal to MAX_LOADED_OBJECTS
    if(slotIndex >= MAX_LOADED_OBJECTS)
	return FALSE;
    // Indicate if the slot is occupied
    return (s_objects[slotIndex].attributes.occupied == TRUE);
}


ObjectSetInUse(
	       OBJECT          *object
	       )
{
    object->attributes.occupied = SET;
}


HandleToObject(
	       TPMI_DH_OBJECT   handle         // IN: handle of the object
	       )
{
    UINT32              index;
    // Return NULL if the handle references a permanent handle because there is no
    // associated OBJECT.
    if(HandleGetType(handle) == TPM_HT_PERMANENT)
	return NULL;
    // In this implementation, the handle is determined by the slot occupied by the
    // object.
    index = handle - TRANSIENT_FIRST;
    pAssert(index < MAX_LOADED_OBJECTS);
    pAssert(s_objects[index].attributes.occupied);
    return &s_objects[index];
}


HandleCoRREBPP (rfbClient* client, int rx, int ry, int rw, int rh)
{
    rfbRREHeader hdr;
    int i;
    CARDBPP pix;
    uint8_t *ptr;
    int x, y, w, h;

    if (!ReadFromRFBServer(client, (char *)&hdr, sz_rfbRREHeader))
	return FALSE;

    hdr.nSubrects = rfbClientSwap32IfLE(hdr.nSubrects);

    if (!ReadFromRFBServer(client, (char *)&pix, sizeof(pix)))
	return FALSE;

    client->GotFillRect(client, rx, ry, rw, rh, pix);

    if (hdr.nSubrects > RFB_BUFFER_SIZE / (4 + (BPP / 8)) || !ReadFromRFBServer(client, client->buffer, hdr.nSubrects * (4 + (BPP / 8))))
	return FALSE;

    ptr = (uint8_t *)client->buffer;

    for (i = 0; i < hdr.nSubrects; i++) {
	pix = *(CARDBPP *)ptr;
	ptr += BPP/8;
	x = *ptr++;
	y = *ptr++;
	w = *ptr++;
	h = *ptr++;

	client->GotFillRect(client, rx+x, ry+y, w, h, pix);
    }

    return TRUE;
}

LibVNCClient: really fix #250


lzw_result lzw_decode_init(
		struct lzw_ctx *ctx,
		const uint8_t *compressed_data,
		uint64_t compressed_data_len,
		uint64_t compressed_data_pos,
		uint8_t code_size,
		const uint8_t ** const stack_base_out,
		const uint8_t ** const stack_pos_out)
{
	struct lzw_dictionary_entry *table = ctx->table;

	/* Initialise the input reading context */
	ctx->input.data = compressed_data;
	ctx->input.data_len = compressed_data_len;
	ctx->input.data_sb_next = compressed_data_pos;

	ctx->input.sb_bit = 0;
	ctx->input.sb_bit_count = 0;

	/* Initialise the dictionary building context */
	ctx->initial_code_size = code_size;

	ctx->clear_code = (1 << code_size) + 0;
	ctx->eoi_code   = (1 << code_size) + 1;

	/* Initialise the standard dictionary entries */
	for (uint32_t i = 0; i < ctx->clear_code; ++i) {
		table[i].first_value = i;
		table[i].last_value  = i;
	}

	*stack_base_out = ctx->stack_base;
	return lzw__clear_codes(ctx, stack_pos_out);
}

libnsgif: fix oob in lzw_decode


lzw_result lzw_context_create(struct lzw_ctx **ctx)
{
	struct lzw_ctx *c = malloc(sizeof(*c));
	if (c == NULL) {
		return LZW_NO_MEM;
	}

	*ctx = c;
	return LZW_OK;
}

libnsgif: fix oob in lzw_decode


static lzw_result lzw__block_advance(struct lzw_read_ctx *ctx)
{
	uint64_t block_size;
	uint64_t next_block_pos = ctx->data_sb_next;
	const uint8_t *data_next = ctx->data + next_block_pos;

	if (next_block_pos >= ctx->data_len) {
		return LZW_NO_DATA;
	}

	block_size = *data_next;

	if ((next_block_pos + block_size) >= ctx->data_len) {
		return LZW_NO_DATA;
	}

	ctx->sb_bit = 0;
	ctx->sb_bit_count = block_size * 8;

	if (block_size == 0) {
		ctx->data_sb_next += 1;
		return LZW_OK_EOD;
	}

	ctx->sb_data = data_next + 1;
	ctx->data_sb_next += block_size + 1;

	return LZW_OK;
}

libnsgif: fix oob in lzw_decode


static lzw_result lzw__clear_codes(
		struct lzw_ctx *ctx,
		const uint8_t ** const stack_pos_out)
{
	uint32_t code;
	uint8_t *stack_pos;

	/* Reset dictionary building context */
	ctx->current_code_size = ctx->initial_code_size + 1;
	ctx->current_code_size_max = (1 << ctx->current_code_size) - 1;;
	ctx->current_entry = (1 << ctx->initial_code_size) + 2;

	/* There might be a sequence of clear codes, so process them all */
	do {
		lzw_result res = lzw__next_code(&ctx->input,
				ctx->current_code_size, &code);
		if (res != LZW_OK) {
			return res;
		}
	} while (code == ctx->clear_code);

	/* The initial code must be from the initial dictionary. */
	if (code > ctx->clear_code) {
		return LZW_BAD_ICODE;
	}

	/* Record this initial code as "previous" code, needed during decode. */
	ctx->previous_code = code;
	ctx->previous_code_first = code;

	/* Reset the stack, and add first non-clear code added as first item. */
	stack_pos = ctx->stack_base;
	*stack_pos++ = code;

	*stack_pos_out = stack_pos;
	return LZW_OK;
}

libnsgif: fix oob in lzw_decode


void lzw_context_destroy(struct lzw_ctx *ctx)
{
	free(ctx);
}

libnsgif: fix oob in lzw_decode


lzw_result lzw_decode(struct lzw_ctx *ctx,
		const uint8_t ** const stack_pos_out)
{
	lzw_result res;
	uint32_t code_new;
	uint32_t code_out;
	uint8_t last_value;
	uint8_t *stack_pos = ctx->stack_base;
	uint32_t clear_code = ctx->clear_code;
	uint32_t current_entry = ctx->current_entry;
	struct lzw_dictionary_entry * const table = ctx->table;

	/* Get a new code from the input */
	res = lzw__next_code(&ctx->input, ctx->current_code_size, &code_new);
	if (res != LZW_OK) {
		return res;
	}

	/* Handle the new code */
	if (code_new == clear_code) {
		/* Got Clear code */
		return lzw__clear_codes(ctx, stack_pos_out);

	} else if (code_new == ctx->eoi_code) {
		/* Got End of Information code */
		return LZW_EOI_CODE;

	} else if (code_new > current_entry) {
		/* Code is invalid */
		return LZW_BAD_CODE;

	} else if (code_new >= 1 << LZW_CODE_MAX) {
		/* Don't access out of bound */
		return LZW_BAD_CODE;

	} else if (code_new < current_entry) {
		/* Code is in table */
		code_out = code_new;
		last_value = table[code_new].first_value;
	} else {
		/* Code not in table */
		*stack_pos++ = ctx->previous_code_first;
		code_out = ctx->previous_code;
		last_value = ctx->previous_code_first;
	}

	/* Add to the dictionary, only if there's space */
	if (current_entry < (1 << LZW_CODE_MAX)) {
		struct lzw_dictionary_entry *entry = table + current_entry;
		entry->last_value     = last_value;
		entry->first_value    = ctx->previous_code_first;
		entry->previous_entry = ctx->previous_code;
		ctx->current_entry++;
	}

	/* Ensure code size is increased, if needed. */
	if (current_entry == ctx->current_code_size_max) {
		if (ctx->current_code_size < LZW_CODE_MAX) {
			ctx->current_code_size++;
			ctx->current_code_size_max =
					(1 << ctx->current_code_size) - 1;
		}
	}

	/* Store details of this code as "previous code" to the context. */
	ctx->previous_code_first = table[code_new].first_value;
	ctx->previous_code = code_new;

	/* Put rest of data for this code on output stack.
	 * Note, in the case of "code not in table", the last entry of the
	 * current code has already been placed on the stack above. */
	while (code_out > clear_code) {
		struct lzw_dictionary_entry *entry = table + code_out;
		*stack_pos++ = entry->last_value;
		code_out = entry->previous_entry;
	}
	*stack_pos++ = table[code_out].last_value;

	*stack_pos_out = stack_pos;
	return LZW_OK;
}

libnsgif: fix oob in lzw_decode


static inline lzw_result lzw__next_code(
		struct lzw_read_ctx *ctx,
		uint8_t code_size,
		uint32_t *code_out)
{
	uint32_t code = 0;
	uint8_t current_bit = ctx->sb_bit & 0x7;
	uint8_t byte_advance = (current_bit + code_size) >> 3;

	assert(byte_advance <= 2);

	if (ctx->sb_bit + code_size <= ctx->sb_bit_count) {
		/* Fast path: code fully inside this sub-block */
		const uint8_t *data = ctx->sb_data + (ctx->sb_bit >> 3);
		switch (byte_advance) {
			case 2: code |= data[2] << 16; /* Fall through */
			case 1: code |= data[1] <<  8; /* Fall through */
			case 0: code |= data[0] <<  0;
		}
		ctx->sb_bit += code_size;
	} else {
		/* Slow path: code spans sub-blocks */
		uint8_t byte = 0;
		uint8_t bits_remaining_0 = (code_size < (8 - current_bit)) ?
				code_size : (8 - current_bit);
		uint8_t bits_remaining_1 = code_size - bits_remaining_0;
		uint8_t bits_used[3] = {
			[0] = bits_remaining_0,
			[1] = bits_remaining_1 < 8 ? bits_remaining_1 : 8,
			[2] = bits_remaining_1 - 8,
		};

		while (true) {
			const uint8_t *data = ctx->sb_data;
			lzw_result res;

			/* Get any data from end of this sub-block */
			while (byte <= byte_advance &&
					ctx->sb_bit < ctx->sb_bit_count) {
				code |= data[ctx->sb_bit >> 3] << (byte << 3);
				ctx->sb_bit += bits_used[byte];
				byte++;
			}

			/* Check if we have all we need */
			if (byte > byte_advance) {
				break;
			}

			/* Move to next sub-block */
			res = lzw__block_advance(ctx);
			if (res != LZW_OK) {
				return res;
			}
		}
	}

	*code_out = (code >> current_bit) & ((1 << code_size) - 1);
	return LZW_OK;
}

libnsgif: fix oob in lzw_decode


static int config_buf(struct usb_configuration *config,
		enum usb_device_speed speed, void *buf, u8 type)
{
	struct usb_config_descriptor	*c = buf;
	void				*next = buf + USB_DT_CONFIG_SIZE;
	int				len;
	struct usb_function		*f;
	int				status;

	len = USB_COMP_EP0_BUFSIZ - USB_DT_CONFIG_SIZE;
	/* write the config descriptor */
	c = buf;
	c->bLength = USB_DT_CONFIG_SIZE;
	c->bDescriptorType = type;
	/* wTotalLength is written later */
	c->bNumInterfaces = config->next_interface_id;
	c->bConfigurationValue = config->bConfigurationValue;
	c->iConfiguration = config->iConfiguration;
	c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes;
	c->bMaxPower = encode_bMaxPower(speed, config);

	/* There may be e.g. OTG descriptors */
	if (config->descriptors) {
		status = usb_descriptor_fillbuf(next, len,
				config->descriptors);
		if (status < 0)
			return status;
		len -= status;
		next += status;
	}

	/* add each function's descriptors */
	list_for_each_entry(f, &config->functions, list) {
		struct usb_descriptor_header **descriptors;

		descriptors = function_descriptors(f, speed);
		if (!descriptors)
			continue;
		status = usb_descriptor_fillbuf(next, len,
			(const struct usb_descriptor_header **) descriptors);
		if (status < 0)
			return status;
		len -= status;
		next += status;
	}

	len = next - buf;
	c->wTotalLength = cpu_to_le16(len);
	return len;
}

USB: gadget: validate interface OS descriptor requests

Stall the control endpoint in case provided index exceeds array size of
MAX_CONFIG_INTERFACES or when the retrieved function pointer is null.

Signed-off-by: Szymon Heidrich <szymon.heidrich@gmail.com>
Cc: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>


static void composite_unbind(struct usb_gadget *gadget)
{
	__composite_unbind(gadget, true);
}


int config_ep_by_speed(struct usb_gadget *g,
			struct usb_function *f,
			struct usb_ep *_ep)
{
	return config_ep_by_speed_and_alt(g, f, _ep, 0);
}


int usb_string_id(struct usb_composite_dev *cdev)
{
	if (cdev->next_string_id < 254) {
		/* string id 0 is reserved by USB spec for list of
		 * supported languages */
		/* 255 reserved as well? -- mina86 */
		cdev->next_string_id++;
		return cdev->next_string_id;
	}
	return -ENODEV;
}


void composite_resume(struct usb_gadget *gadget)
{
	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
	struct usb_function		*f;
	unsigned			maxpower;

	/* REVISIT:  should we have config level
	 * suspend/resume callbacks?
	 */
	DBG(cdev, "resume\n");
	if (cdev->driver->resume)
		cdev->driver->resume(cdev);
	if (cdev->config) {
		list_for_each_entry(f, &cdev->config->functions, list) {
			if (f->resume)
				f->resume(f);
		}

		maxpower = cdev->config->MaxPower ?
			cdev->config->MaxPower : CONFIG_USB_GADGET_VBUS_DRAW;
		if (gadget->speed < USB_SPEED_SUPER)
			maxpower = min(maxpower, 500U);
		else
			maxpower = min(maxpower, 900U);

		if (maxpower > USB_SELF_POWER_VBUS_MAX_DRAW)
			usb_gadget_clear_selfpowered(gadget);

		usb_gadget_vbus_draw(gadget, maxpower);
	}

	cdev->suspended = 0;
}


int config_ep_by_speed_and_alt(struct usb_gadget *g,
				struct usb_function *f,
				struct usb_ep *_ep,
				u8 alt)
{
	struct usb_endpoint_descriptor *chosen_desc = NULL;
	struct usb_interface_descriptor *int_desc = NULL;
	struct usb_descriptor_header **speed_desc = NULL;

	struct usb_ss_ep_comp_descriptor *comp_desc = NULL;
	int want_comp_desc = 0;

	struct usb_descriptor_header **d_spd; /* cursor for speed desc */
	struct usb_composite_dev *cdev;
	bool incomplete_desc = false;

	if (!g || !f || !_ep)
		return -EIO;

	/* select desired speed */
	switch (g->speed) {
	case USB_SPEED_SUPER_PLUS:
		if (gadget_is_superspeed_plus(g)) {
			if (f->ssp_descriptors) {
				speed_desc = f->ssp_descriptors;
				want_comp_desc = 1;
				break;
			}
			incomplete_desc = true;
		}
		fallthrough;
	case USB_SPEED_SUPER:
		if (gadget_is_superspeed(g)) {
			if (f->ss_descriptors) {
				speed_desc = f->ss_descriptors;
				want_comp_desc = 1;
				break;
			}
			incomplete_desc = true;
		}
		fallthrough;
	case USB_SPEED_HIGH:
		if (gadget_is_dualspeed(g)) {
			if (f->hs_descriptors) {
				speed_desc = f->hs_descriptors;
				break;
			}
			incomplete_desc = true;
		}
		fallthrough;
	default:
		speed_desc = f->fs_descriptors;
	}

	cdev = get_gadget_data(g);
	if (incomplete_desc)
		WARNING(cdev,
			"%s doesn't hold the descriptors for current speed\n",
			f->name);

	/* find correct alternate setting descriptor */
	for_each_desc(speed_desc, d_spd, USB_DT_INTERFACE) {
		int_desc = (struct usb_interface_descriptor *)*d_spd;

		if (int_desc->bAlternateSetting == alt) {
			speed_desc = d_spd;
			goto intf_found;
		}
	}
	return -EIO;

intf_found:
	/* find descriptors */
	for_each_desc(speed_desc, d_spd, USB_DT_ENDPOINT) {
		chosen_desc = (struct usb_endpoint_descriptor *)*d_spd;
		if (chosen_desc->bEndpointAddress == _ep->address)
			goto ep_found;
	}
	return -EIO;

ep_found:
	/* commit results */
	_ep->maxpacket = usb_endpoint_maxp(chosen_desc);
	_ep->desc = chosen_desc;
	_ep->comp_desc = NULL;
	_ep->maxburst = 0;
	_ep->mult = 1;

	if (g->speed == USB_SPEED_HIGH && (usb_endpoint_xfer_isoc(_ep->desc) ||
				usb_endpoint_xfer_int(_ep->desc)))
		_ep->mult = usb_endpoint_maxp_mult(_ep->desc);

	if (!want_comp_desc)
		return 0;

	/*
	 * Companion descriptor should follow EP descriptor
	 * USB 3.0 spec, #9.6.7
	 */
	comp_desc = (struct usb_ss_ep_comp_descriptor *)*(++d_spd);
	if (!comp_desc ||
	    (comp_desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP))
		return -EIO;
	_ep->comp_desc = comp_desc;
	if (g->speed >= USB_SPEED_SUPER) {
		switch (usb_endpoint_type(_ep->desc)) {
		case USB_ENDPOINT_XFER_ISOC:
			/* mult: bits 1:0 of bmAttributes */
			_ep->mult = (comp_desc->bmAttributes & 0x3) + 1;
			fallthrough;
		case USB_ENDPOINT_XFER_BULK:
		case USB_ENDPOINT_XFER_INT:
			_ep->maxburst = comp_desc->bMaxBurst + 1;
			break;
		default:
			if (comp_desc->bMaxBurst != 0)
				ERROR(cdev, "ep0 bMaxBurst must be 0\n");
			_ep->maxburst = 1;
			break;
		}
	}
	return 0;
}


void composite_reset(struct usb_gadget *gadget)
{
	/*
	 * Section 1.4.13 Standard Downstream Port of the USB battery charging
	 * specification v1.2 states that a device connected on a SDP shall only
	 * draw at max 100mA while in a connected, but unconfigured state.
	 */
	usb_gadget_vbus_draw(gadget, 100);
	__composite_disconnect(gadget);
}


static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf)
{
	const struct usb_gadget_strings	*s;
	__le16				language;
	__le16				*tmp;

	while (*sp) {
		s = *sp;
		language = cpu_to_le16(s->language);
		for (tmp = buf; *tmp && tmp < &buf[USB_MAX_STRING_LEN]; tmp++) {
			if (*tmp == language)
				goto repeat;
		}
		*tmp++ = language;
repeat:
		sp++;
	}
}


void usb_composite_overwrite_options(struct usb_composite_dev *cdev,
		struct usb_composite_overwrite *covr)
{
	struct usb_device_descriptor	*desc = &cdev->desc;
	struct usb_gadget_strings	*gstr = cdev->driver->strings[0];
	struct usb_string		*dev_str = gstr->strings;

	if (covr->idVendor)
		desc->idVendor = cpu_to_le16(covr->idVendor);

	if (covr->idProduct)
		desc->idProduct = cpu_to_le16(covr->idProduct);

	if (covr->bcdDevice)
		desc->bcdDevice = cpu_to_le16(covr->bcdDevice);

	if (covr->serial_number) {
		desc->iSerialNumber = dev_str[USB_GADGET_SERIAL_IDX].id;
		dev_str[USB_GADGET_SERIAL_IDX].s = covr->serial_number;
	}
	if (covr->manufacturer) {
		desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id;
		dev_str[USB_GADGET_MANUFACTURER_IDX].s = covr->manufacturer;

	} else if (!strlen(dev_str[USB_GADGET_MANUFACTURER_IDX].s)) {
		desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id;
		cdev->def_manufacturer = composite_default_mfr(cdev->gadget);
		dev_str[USB_GADGET_MANUFACTURER_IDX].s = cdev->def_manufacturer;
	}

	if (covr->product) {
		desc->iProduct = dev_str[USB_GADGET_PRODUCT_IDX].id;
		dev_str[USB_GADGET_PRODUCT_IDX].s = covr->product;
	}
}


composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
{
	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
	struct usb_request		*req = cdev->req;
	int				value = -EOPNOTSUPP;
	int				status = 0;
	u16				w_index = le16_to_cpu(ctrl->wIndex);
	u8				intf = w_index & 0xFF;
	u16				w_value = le16_to_cpu(ctrl->wValue);
	u16				w_length = le16_to_cpu(ctrl->wLength);
	struct usb_function		*f = NULL;
	u8				endp;

	if (w_length > USB_COMP_EP0_BUFSIZ) {
		if (ctrl->bRequestType & USB_DIR_IN) {
			/* Cast away the const, we are going to overwrite on purpose. */
			__le16 *temp = (__le16 *)&ctrl->wLength;

			*temp = cpu_to_le16(USB_COMP_EP0_BUFSIZ);
			w_length = USB_COMP_EP0_BUFSIZ;
		} else {
			goto done;
		}
	}

	/* partial re-init of the response message; the function or the
	 * gadget might need to intercept e.g. a control-OUT completion
	 * when we delegate to it.
	 */
	req->zero = 0;
	req->context = cdev;
	req->complete = composite_setup_complete;
	req->length = 0;
	gadget->ep0->driver_data = cdev;

	/*
	 * Don't let non-standard requests match any of the cases below
	 * by accident.
	 */
	if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD)
		goto unknown;

	switch (ctrl->bRequest) {

	/* we handle all standard USB descriptors */
	case USB_REQ_GET_DESCRIPTOR:
		if (ctrl->bRequestType != USB_DIR_IN)
			goto unknown;
		switch (w_value >> 8) {

		case USB_DT_DEVICE:
			cdev->desc.bNumConfigurations =
				count_configs(cdev, USB_DT_DEVICE);
			cdev->desc.bMaxPacketSize0 =
				cdev->gadget->ep0->maxpacket;
			if (gadget_is_superspeed(gadget)) {
				if (gadget->speed >= USB_SPEED_SUPER) {
					cdev->desc.bcdUSB = cpu_to_le16(0x0320);
					cdev->desc.bMaxPacketSize0 = 9;
				} else {
					cdev->desc.bcdUSB = cpu_to_le16(0x0210);
				}
			} else {
				if (gadget->lpm_capable)
					cdev->desc.bcdUSB = cpu_to_le16(0x0201);
				else
					cdev->desc.bcdUSB = cpu_to_le16(0x0200);
			}

			value = min(w_length, (u16) sizeof cdev->desc);
			memcpy(req->buf, &cdev->desc, value);
			break;
		case USB_DT_DEVICE_QUALIFIER:
			if (!gadget_is_dualspeed(gadget) ||
			    gadget->speed >= USB_SPEED_SUPER)
				break;
			device_qual(cdev);
			value = min_t(int, w_length,
				sizeof(struct usb_qualifier_descriptor));
			break;
		case USB_DT_OTHER_SPEED_CONFIG:
			if (!gadget_is_dualspeed(gadget) ||
			    gadget->speed >= USB_SPEED_SUPER)
				break;
			fallthrough;
		case USB_DT_CONFIG:
			value = config_desc(cdev, w_value);
			if (value >= 0)
				value = min(w_length, (u16) value);
			break;
		case USB_DT_STRING:
			value = get_string(cdev, req->buf,
					w_index, w_value & 0xff);
			if (value >= 0)
				value = min(w_length, (u16) value);
			break;
		case USB_DT_BOS:
			if (gadget_is_superspeed(gadget) ||
			    gadget->lpm_capable) {
				value = bos_desc(cdev);
				value = min(w_length, (u16) value);
			}
			break;
		case USB_DT_OTG:
			if (gadget_is_otg(gadget)) {
				struct usb_configuration *config;
				int otg_desc_len = 0;

				if (cdev->config)
					config = cdev->config;
				else
					config = list_first_entry(
							&cdev->configs,
						struct usb_configuration, list);
				if (!config)
					goto done;

				if (gadget->otg_caps &&
					(gadget->otg_caps->otg_rev >= 0x0200))
					otg_desc_len += sizeof(
						struct usb_otg20_descriptor);
				else
					otg_desc_len += sizeof(
						struct usb_otg_descriptor);

				value = min_t(int, w_length, otg_desc_len);
				memcpy(req->buf, config->descriptors[0], value);
			}
			break;
		}
		break;

	/* any number of configs can work */
	case USB_REQ_SET_CONFIGURATION:
		if (ctrl->bRequestType != 0)
			goto unknown;
		if (gadget_is_otg(gadget)) {
			if (gadget->a_hnp_support)
				DBG(cdev, "HNP available\n");
			else if (gadget->a_alt_hnp_support)
				DBG(cdev, "HNP on another port\n");
			else
				VDBG(cdev, "HNP inactive\n");
		}
		spin_lock(&cdev->lock);
		value = set_config(cdev, ctrl, w_value);
		spin_unlock(&cdev->lock);
		break;
	case USB_REQ_GET_CONFIGURATION:
		if (ctrl->bRequestType != USB_DIR_IN)
			goto unknown;
		if (cdev->config)
			*(u8 *)req->buf = cdev->config->bConfigurationValue;
		else
			*(u8 *)req->buf = 0;
		value = min(w_length, (u16) 1);
		break;

	/* function drivers must handle get/set altsetting */
	case USB_REQ_SET_INTERFACE:
		if (ctrl->bRequestType != USB_RECIP_INTERFACE)
			goto unknown;
		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
			break;
		f = cdev->config->interface[intf];
		if (!f)
			break;

		/*
		 * If there's no get_alt() method, we know only altsetting zero
		 * works. There is no need to check if set_alt() is not NULL
		 * as we check this in usb_add_function().
		 */
		if (w_value && !f->get_alt)
			break;

		spin_lock(&cdev->lock);
		value = f->set_alt(f, w_index, w_value);
		if (value == USB_GADGET_DELAYED_STATUS) {
			DBG(cdev,
			 "%s: interface %d (%s) requested delayed status\n",
					__func__, intf, f->name);
			cdev->delayed_status++;
			DBG(cdev, "delayed_status count %d\n",
					cdev->delayed_status);
		}
		spin_unlock(&cdev->lock);
		break;
	case USB_REQ_GET_INTERFACE:
		if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))
			goto unknown;
		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
			break;
		f = cdev->config->interface[intf];
		if (!f)
			break;
		/* lots of interfaces only need altsetting zero... */
		value = f->get_alt ? f->get_alt(f, w_index) : 0;
		if (value < 0)
			break;
		*((u8 *)req->buf) = value;
		value = min(w_length, (u16) 1);
		break;
	case USB_REQ_GET_STATUS:
		if (gadget_is_otg(gadget) && gadget->hnp_polling_support &&
						(w_index == OTG_STS_SELECTOR)) {
			if (ctrl->bRequestType != (USB_DIR_IN |
							USB_RECIP_DEVICE))
				goto unknown;
			*((u8 *)req->buf) = gadget->host_request_flag;
			value = 1;
			break;
		}

		/*
		 * USB 3.0 additions:
		 * Function driver should handle get_status request. If such cb
		 * wasn't supplied we respond with default value = 0
		 * Note: function driver should supply such cb only for the
		 * first interface of the function
		 */
		if (!gadget_is_superspeed(gadget))
			goto unknown;
		if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE))
			goto unknown;
		value = 2;	/* This is the length of the get_status reply */
		put_unaligned_le16(0, req->buf);
		if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
			break;
		f = cdev->config->interface[intf];
		if (!f)
			break;
		status = f->get_status ? f->get_status(f) : 0;
		if (status < 0)
			break;
		put_unaligned_le16(status & 0x0000ffff, req->buf);
		break;
	/*
	 * Function drivers should handle SetFeature/ClearFeature
	 * (FUNCTION_SUSPEND) request. function_suspend cb should be supplied
	 * only for the first interface of the function
	 */
	case USB_REQ_CLEAR_FEATURE:
	case USB_REQ_SET_FEATURE:
		if (!gadget_is_superspeed(gadget))
			goto unknown;
		if (ctrl->bRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE))
			goto unknown;
		switch (w_value) {
		case USB_INTRF_FUNC_SUSPEND:
			if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
				break;
			f = cdev->config->interface[intf];
			if (!f)
				break;
			value = 0;
			if (f->func_suspend)
				value = f->func_suspend(f, w_index >> 8);
			if (value < 0) {
				ERROR(cdev,
				      "func_suspend() returned error %d\n",
				      value);
				value = 0;
			}
			break;
		}
		break;
	default:
unknown:
		/*
		 * OS descriptors handling
		 */
		if (cdev->use_os_string && cdev->os_desc_config &&
		    (ctrl->bRequestType & USB_TYPE_VENDOR) &&
		    ctrl->bRequest == cdev->b_vendor_code) {
			struct usb_configuration	*os_desc_cfg;
			u8				*buf;
			int				interface;
			int				count = 0;

			req = cdev->os_desc_req;
			req->context = cdev;
			req->complete = composite_setup_complete;
			buf = req->buf;
			os_desc_cfg = cdev->os_desc_config;
			w_length = min_t(u16, w_length, USB_COMP_EP0_OS_DESC_BUFSIZ);
			memset(buf, 0, w_length);
			buf[5] = 0x01;
			switch (ctrl->bRequestType & USB_RECIP_MASK) {
			case USB_RECIP_DEVICE:
				if (w_index != 0x4 || (w_value >> 8))
					break;
				buf[6] = w_index;
				/* Number of ext compat interfaces */
				count = count_ext_compat(os_desc_cfg);
				buf[8] = count;
				count *= 24; /* 24 B/ext compat desc */
				count += 16; /* header */
				put_unaligned_le32(count, buf);
				value = w_length;
				if (w_length > 0x10) {
					value = fill_ext_compat(os_desc_cfg, buf);
					value = min_t(u16, w_length, value);
				}
				break;
			case USB_RECIP_INTERFACE:
				if (w_index != 0x5 || (w_value >> 8))
					break;
				interface = w_value & 0xFF;
				if (interface >= MAX_CONFIG_INTERFACES ||
				    !os_desc_cfg->interface[interface])
					break;
				buf[6] = w_index;
				count = count_ext_prop(os_desc_cfg,
					interface);
				put_unaligned_le16(count, buf + 8);
				count = len_ext_prop(os_desc_cfg,
					interface);
				put_unaligned_le32(count, buf);
				value = w_length;
				if (w_length > 0x0A) {
					value = fill_ext_prop(os_desc_cfg,
							      interface, buf);
					if (value >= 0)
						value = min_t(u16, w_length, value);
				}
				break;
			}

			goto check_value;
		}

		VDBG(cdev,
			"non-core control req%02x.%02x v%04x i%04x l%d\n",
			ctrl->bRequestType, ctrl->bRequest,
			w_value, w_index, w_length);

		/* functions always handle their interfaces and endpoints...
		 * punt other recipients (other, WUSB, ...) to the current
		 * configuration code.
		 */
		if (cdev->config) {
			list_for_each_entry(f, &cdev->config->functions, list)
				if (f->req_match &&
				    f->req_match(f, ctrl, false))
					goto try_fun_setup;
		} else {
			struct usb_configuration *c;
			list_for_each_entry(c, &cdev->configs, list)
				list_for_each_entry(f, &c->functions, list)
					if (f->req_match &&
					    f->req_match(f, ctrl, true))
						goto try_fun_setup;
		}
		f = NULL;

		switch (ctrl->bRequestType & USB_RECIP_MASK) {
		case USB_RECIP_INTERFACE:
			if (!cdev->config || intf >= MAX_CONFIG_INTERFACES)
				break;
			f = cdev->config->interface[intf];
			break;

		case USB_RECIP_ENDPOINT:
			if (!cdev->config)
				break;
			endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f);
			list_for_each_entry(f, &cdev->config->functions, list) {
				if (test_bit(endp, f->endpoints))
					break;
			}
			if (&f->list == &cdev->config->functions)
				f = NULL;
			break;
		}
try_fun_setup:
		if (f && f->setup)
			value = f->setup(f, ctrl);
		else {
			struct usb_configuration	*c;

			c = cdev->config;
			if (!c)
				goto done;

			/* try current config's setup */
			if (c->setup) {
				value = c->setup(c, ctrl);
				goto done;
			}

			/* try the only function in the current config */
			if (!list_is_singular(&c->functions))
				goto done;
			f = list_first_entry(&c->functions, struct usb_function,
					     list);
			if (f->setup)
				value = f->setup(f, ctrl);
		}

		goto done;
	}

check_value:
	/* respond with data transfer before status phase? */
	if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) {
		req->length = value;
		req->context = cdev;
		req->zero = value < w_length;
		value = composite_ep0_queue(cdev, req, GFP_ATOMIC);
		if (value < 0) {
			DBG(cdev, "ep_queue --> %d\n", value);
			req->status = 0;
			composite_setup_complete(gadget->ep0, req);
		}
	} else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) {
		WARN(cdev,
			"%s: Delayed status not supported for w_length != 0",
			__func__);
	}

done:
	/* device either stalls (value < 0) or reports success */
	return value;
}


static struct usb_gadget_strings **get_containers_gs(
		struct usb_gadget_string_container *uc)
{
	return (struct usb_gadget_strings **)uc->stash;
}


void usb_remove_function(struct usb_configuration *c, struct usb_function *f)
{
	if (f->disable)
		f->disable(f);

	bitmap_zero(f->endpoints, 32);
	list_del(&f->list);
	if (f->unbind)
		f->unbind(c, f);

	if (f->bind_deactivated)
		usb_function_activate(f);
}


void usb_composite_unregister(struct usb_composite_driver *driver)
{
	usb_gadget_unregister_driver(&driver->gadget_driver);
}


static char *composite_default_mfr(struct usb_gadget *gadget)
{
	return kasprintf(GFP_KERNEL, "%s %s with %s", init_utsname()->sysname,
			 init_utsname()->release, gadget->name);
}


static int config_desc(struct usb_composite_dev *cdev, unsigned w_value)
{
	struct usb_gadget		*gadget = cdev->gadget;
	struct usb_configuration	*c;
	struct list_head		*pos;
	u8				type = w_value >> 8;
	enum usb_device_speed		speed = USB_SPEED_UNKNOWN;

	if (gadget->speed >= USB_SPEED_SUPER)
		speed = gadget->speed;
	else if (gadget_is_dualspeed(gadget)) {
		int	hs = 0;
		if (gadget->speed == USB_SPEED_HIGH)
			hs = 1;
		if (type == USB_DT_OTHER_SPEED_CONFIG)
			hs = !hs;
		if (hs)
			speed = USB_SPEED_HIGH;

	}

	/* This is a lookup by config *INDEX* */
	w_value &= 0xff;

	pos = &cdev->configs;
	c = cdev->os_desc_config;
	if (c)
		goto check_config;

	while ((pos = pos->next) !=  &cdev->configs) {
		c = list_entry(pos, typeof(*c), list);

		/* skip OS Descriptors config which is handled separately */
		if (c == cdev->os_desc_config)
			continue;

check_config:
		/* ignore configs that won't work at this speed */
		switch (speed) {
		case USB_SPEED_SUPER_PLUS:
			if (!c->superspeed_plus)
				continue;
			break;
		case USB_SPEED_SUPER:
			if (!c->superspeed)
				continue;
			break;
		case USB_SPEED_HIGH:
			if (!c->highspeed)
				continue;
			break;
		default:
			if (!c->fullspeed)
				continue;
		}

		if (w_value == 0)
			return config_buf(c, speed, cdev->req->buf, type);
		w_value--;
	}
	return -EINVAL;
}


int usb_add_config_only(struct usb_composite_dev *cdev,
		struct usb_configuration *config)
{
	struct usb_configuration *c;

	if (!config->bConfigurationValue)
		return -EINVAL;

	/* Prevent duplicate configuration identifiers */
	list_for_each_entry(c, &cdev->configs, list) {
		if (c->bConfigurationValue == config->bConfigurationValue)
			return -EBUSY;
	}

	config->cdev = cdev;
	list_add_tail(&config->list, &cdev->configs);

	INIT_LIST_HEAD(&config->functions);
	config->next_interface_id = 0;
	memset(config->interface, 0, sizeof(config->interface));

	return 0;
}


static int get_string(struct usb_composite_dev *cdev,
		void *buf, u16 language, int id)
{
	struct usb_composite_driver	*composite = cdev->driver;
	struct usb_gadget_string_container *uc;
	struct usb_configuration	*c;
	struct usb_function		*f;
	int				len;

	/* Yes, not only is USB's i18n support probably more than most
	 * folk will ever care about ... also, it's all supported here.
	 * (Except for UTF8 support for Unicode's "Astral Planes".)
	 */

	/* 0 == report all available language codes */
	if (id == 0) {
		struct usb_string_descriptor	*s = buf;
		struct usb_gadget_strings	**sp;

		memset(s, 0, 256);
		s->bDescriptorType = USB_DT_STRING;

		sp = composite->strings;
		if (sp)
			collect_langs(sp, s->wData);

		list_for_each_entry(c, &cdev->configs, list) {
			sp = c->strings;
			if (sp)
				collect_langs(sp, s->wData);

			list_for_each_entry(f, &c->functions, list) {
				sp = f->strings;
				if (sp)
					collect_langs(sp, s->wData);
			}
		}
		list_for_each_entry(uc, &cdev->gstrings, list) {
			struct usb_gadget_strings **sp;

			sp = get_containers_gs(uc);
			collect_langs(sp, s->wData);
		}

		for (len = 0; len <= USB_MAX_STRING_LEN && s->wData[len]; len++)
			continue;
		if (!len)
			return -EINVAL;

		s->bLength = 2 * (len + 1);
		return s->bLength;
	}

	if (cdev->use_os_string && language == 0 && id == OS_STRING_IDX) {
		struct usb_os_string *b = buf;
		b->bLength = sizeof(*b);
		b->bDescriptorType = USB_DT_STRING;
		compiletime_assert(
			sizeof(b->qwSignature) == sizeof(cdev->qw_sign),
			"qwSignature size must be equal to qw_sign");
		memcpy(&b->qwSignature, cdev->qw_sign, sizeof(b->qwSignature));
		b->bMS_VendorCode = cdev->b_vendor_code;
		b->bPad = 0;
		return sizeof(*b);
	}

	list_for_each_entry(uc, &cdev->gstrings, list) {
		struct usb_gadget_strings **sp;

		sp = get_containers_gs(uc);
		len = lookup_string(sp, buf, language, id);
		if (len > 0)
			return len;
	}

	/* String IDs are device-scoped, so we look up each string
	 * table we're told about.  These lookups are infrequent;
	 * simpler-is-better here.
	 */
	if (composite->strings) {
		len = lookup_string(composite->strings, buf, language, id);
		if (len > 0)
			return len;
	}
	list_for_each_entry(c, &cdev->configs, list) {
		if (c->strings) {
			len = lookup_string(c->strings, buf, language, id);
			if (len > 0)
				return len;
		}
		list_for_each_entry(f, &c->functions, list) {
			if (!f->strings)
				continue;
			len = lookup_string(f->strings, buf, language, id);
			if (len > 0)
				return len;
		}
	}
	return -EINVAL;
}


function_descriptors(struct usb_function *f,
		     enum usb_device_speed speed)
{
	struct usb_descriptor_header **descriptors;

	/*
	 * NOTE: we try to help gadget drivers which might not be setting
	 * max_speed appropriately.
	 */

	switch (speed) {
	case USB_SPEED_SUPER_PLUS:
		descriptors = f->ssp_descriptors;
		if (descriptors)
			break;
		fallthrough;
	case USB_SPEED_SUPER:
		descriptors = f->ss_descriptors;
		if (descriptors)
			break;
		fallthrough;
	case USB_SPEED_HIGH:
		descriptors = f->hs_descriptors;
		if (descriptors)
			break;
		fallthrough;
	default:
		descriptors = f->fs_descriptors;
	}

	/*
	 * if we can't find any descriptors at all, then this gadget deserves to
	 * Oops with a NULL pointer dereference
	 */

	return descriptors;
}


void usb_remove_config(struct usb_composite_dev *cdev,
		      struct usb_configuration *config)
{
	unsigned long flags;

	spin_lock_irqsave(&cdev->lock, flags);

	if (cdev->config == config)
		reset_config(cdev);

	spin_unlock_irqrestore(&cdev->lock, flags);

	remove_config(cdev, config);
}


int usb_function_activate(struct usb_function *function)
{
	struct usb_composite_dev	*cdev = function->config->cdev;
	unsigned long			flags;
	int				status = 0;

	spin_lock_irqsave(&cdev->lock, flags);

	if (WARN_ON(cdev->deactivations == 0))
		status = -EINVAL;
	else {
		cdev->deactivations--;
		if (cdev->deactivations == 0) {
			spin_unlock_irqrestore(&cdev->lock, flags);
			status = usb_gadget_activate(cdev->gadget);
			spin_lock_irqsave(&cdev->lock, flags);
		}
	}

	spin_unlock_irqrestore(&cdev->lock, flags);
	return status;
}


int usb_interface_id(struct usb_configuration *config,
		struct usb_function *function)
{
	unsigned id = config->next_interface_id;

	if (id < MAX_CONFIG_INTERFACES) {
		config->interface[id] = function;
		config->next_interface_id = id + 1;
		return id;
	}
	return -ENODEV;
}


int composite_dev_prepare(struct usb_composite_driver *composite,
		struct usb_composite_dev *cdev)
{
	struct usb_gadget *gadget = cdev->gadget;
	int ret = -ENOMEM;

	/* preallocate control response and buffer */
	cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
	if (!cdev->req)
		return -ENOMEM;

	cdev->req->buf = kzalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL);
	if (!cdev->req->buf)
		goto fail;

	ret = device_create_file(&gadget->dev, &dev_attr_suspended);
	if (ret)
		goto fail_dev;

	cdev->req->complete = composite_setup_complete;
	cdev->req->context = cdev;
	gadget->ep0->driver_data = cdev;

	cdev->driver = composite;

	/*
	 * As per USB compliance update, a device that is actively drawing
	 * more than 100mA from USB must report itself as bus-powered in
	 * the GetStatus(DEVICE) call.
	 */
	if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
		usb_gadget_set_selfpowered(gadget);

	/* interface and string IDs start at zero via kzalloc.
	 * we force endpoints to start unassigned; few controller
	 * drivers will zero ep->driver_data.
	 */
	usb_ep_autoconfig_reset(gadget);
	return 0;
fail_dev:
	kfree(cdev->req->buf);
fail:
	usb_ep_free_request(gadget->ep0, cdev->req);
	cdev->req = NULL;
	return ret;
}


int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
				  struct usb_ep *ep0)
{
	int ret = 0;

	cdev->os_desc_req = usb_ep_alloc_request(ep0, GFP_KERNEL);
	if (!cdev->os_desc_req) {
		ret = -ENOMEM;
		goto end;
	}

	cdev->os_desc_req->buf = kmalloc(USB_COMP_EP0_OS_DESC_BUFSIZ,
					 GFP_KERNEL);
	if (!cdev->os_desc_req->buf) {
		ret = -ENOMEM;
		usb_ep_free_request(ep0, cdev->os_desc_req);
		goto end;
	}
	cdev->os_desc_req->context = cdev;
	cdev->os_desc_req->complete = composite_setup_complete;
end:
	return ret;
}


static int count_configs(struct usb_composite_dev *cdev, unsigned type)
{
	struct usb_gadget		*gadget = cdev->gadget;
	struct usb_configuration	*c;
	unsigned			count = 0;
	int				hs = 0;
	int				ss = 0;
	int				ssp = 0;

	if (gadget_is_dualspeed(gadget)) {
		if (gadget->speed == USB_SPEED_HIGH)
			hs = 1;
		if (gadget->speed == USB_SPEED_SUPER)
			ss = 1;
		if (gadget->speed == USB_SPEED_SUPER_PLUS)
			ssp = 1;
		if (type == USB_DT_DEVICE_QUALIFIER)
			hs = !hs;
	}
	list_for_each_entry(c, &cdev->configs, list) {
		/* ignore configs that won't work at this speed */
		if (ssp) {
			if (!c->superspeed_plus)
				continue;
		} else if (ss) {
			if (!c->superspeed)
				continue;
		} else if (hs) {
			if (!c->highspeed)
				continue;
		} else {
			if (!c->fullspeed)
				continue;
		}
		count++;
	}
	return count;
}


void composite_suspend(struct usb_gadget *gadget)
{
	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
	struct usb_function		*f;

	/* REVISIT:  should we have config level
	 * suspend/resume callbacks?
	 */
	DBG(cdev, "suspend\n");
	if (cdev->config) {
		list_for_each_entry(f, &cdev->config->functions, list) {
			if (f->suspend)
				f->suspend(f);
		}
	}
	if (cdev->driver->suspend)
		cdev->driver->suspend(cdev);

	cdev->suspended = 1;

	usb_gadget_set_selfpowered(gadget);
	usb_gadget_vbus_draw(gadget, 2);
}


static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
{
	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
	struct usb_gadget_strings	*gstr = cdev->driver->strings[0];
	struct usb_string		*dev_str = gstr->strings;

	/* composite_disconnect() must already have been called
	 * by the underlying peripheral controller driver!
	 * so there's no i/o concurrency that could affect the
	 * state protected by cdev->lock.
	 */
	WARN_ON(cdev->config);

	while (!list_empty(&cdev->configs)) {
		struct usb_configuration	*c;
		c = list_first_entry(&cdev->configs,
				struct usb_configuration, list);
		remove_config(cdev, c);
	}
	if (cdev->driver->unbind && unbind_driver)
		cdev->driver->unbind(cdev);

	composite_dev_cleanup(cdev);

	if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer)
		dev_str[USB_GADGET_MANUFACTURER_IDX].s = "";

	kfree(cdev->def_manufacturer);
	kfree(cdev);
	set_gadget_data(gadget, NULL);
}


static int count_ext_prop(struct usb_configuration *c, int interface)
{
	struct usb_function *f;
	int j;

	f = c->interface[interface];
	for (j = 0; j < f->os_desc_n; ++j) {
		struct usb_os_desc *d;

		if (interface != f->os_desc_table[j].if_id)
			continue;
		d = f->os_desc_table[j].os_desc;
		if (d && d->ext_compat_id)
			return d->ext_prop_count;
	}
	return 0;
}


static void update_unchanged_dev_desc(struct usb_device_descriptor *new,
		const struct usb_device_descriptor *old)
{
	__le16 idVendor;
	__le16 idProduct;
	__le16 bcdDevice;
	u8 iSerialNumber;
	u8 iManufacturer;
	u8 iProduct;

	/*
	 * these variables may have been set in
	 * usb_composite_overwrite_options()
	 */
	idVendor = new->idVendor;
	idProduct = new->idProduct;
	bcdDevice = new->bcdDevice;
	iSerialNumber = new->iSerialNumber;
	iManufacturer = new->iManufacturer;
	iProduct = new->iProduct;

	*new = *old;
	if (idVendor)
		new->idVendor = idVendor;
	if (idProduct)
		new->idProduct = idProduct;
	if (bcdDevice)
		new->bcdDevice = bcdDevice;
	else
		new->bcdDevice = cpu_to_le16(get_default_bcdDevice());
	if (iSerialNumber)
		new->iSerialNumber = iSerialNumber;
	if (iManufacturer)
		new->iManufacturer = iManufacturer;
	if (iProduct)
		new->iProduct = iProduct;
}


next_desc(struct usb_descriptor_header **t, u8 desc_type)
{
	for (; *t; t++) {
		if ((*t)->bDescriptorType == desc_type)
			return t;
	}
	return NULL;
}


static void device_qual(struct usb_composite_dev *cdev)
{
	struct usb_qualifier_descriptor	*qual = cdev->req->buf;

	qual->bLength = sizeof(*qual);
	qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER;
	/* POLICY: same bcdUSB and device type info at both speeds */
	qual->bcdUSB = cdev->desc.bcdUSB;
	qual->bDeviceClass = cdev->desc.bDeviceClass;
	qual->bDeviceSubClass = cdev->desc.bDeviceSubClass;
	qual->bDeviceProtocol = cdev->desc.bDeviceProtocol;
	/* ASSUME same EP0 fifo size at both speeds */
	qual->bMaxPacketSize0 = cdev->gadget->ep0->maxpacket;
	qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER);
	qual->bRESERVED = 0;
}


void composite_dev_cleanup(struct usb_composite_dev *cdev)
{
	struct usb_gadget_string_container *uc, *tmp;
	struct usb_ep			   *ep, *tmp_ep;

	list_for_each_entry_safe(uc, tmp, &cdev->gstrings, list) {
		list_del(&uc->list);
		kfree(uc);
	}
	if (cdev->os_desc_req) {
		if (cdev->os_desc_pending)
			usb_ep_dequeue(cdev->gadget->ep0, cdev->os_desc_req);

		kfree(cdev->os_desc_req->buf);
		cdev->os_desc_req->buf = NULL;
		usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req);
		cdev->os_desc_req = NULL;
	}
	if (cdev->req) {
		if (cdev->setup_pending)
			usb_ep_dequeue(cdev->gadget->ep0, cdev->req);

		kfree(cdev->req->buf);
		cdev->req->buf = NULL;
		usb_ep_free_request(cdev->gadget->ep0, cdev->req);
		cdev->req = NULL;
	}
	cdev->next_string_id = 0;
	device_remove_file(&cdev->gadget->dev, &dev_attr_suspended);

	/*
	 * Some UDC backends have a dynamic EP allocation scheme.
	 *
	 * In that case, the dispose() callback is used to notify the
	 * backend that the EPs are no longer in use.
	 *
	 * Note: The UDC backend can remove the EP from the ep_list as
	 *	 a result, so we need to use the _safe list iterator.
	 */
	list_for_each_entry_safe(ep, tmp_ep,
				 &cdev->gadget->ep_list, ep_list) {
		if (ep->ops->dispose)
			ep->ops->dispose(ep);
	}
}


int usb_function_deactivate(struct usb_function *function)
{
	struct usb_composite_dev	*cdev = function->config->cdev;
	unsigned long			flags;
	int				status = 0;

	spin_lock_irqsave(&cdev->lock, flags);

	if (cdev->deactivations == 0) {
		spin_unlock_irqrestore(&cdev->lock, flags);
		status = usb_gadget_deactivate(cdev->gadget);
		spin_lock_irqsave(&cdev->lock, flags);
	}
	if (status == 0)
		cdev->deactivations++;

	spin_unlock_irqrestore(&cdev->lock, flags);
	return status;
}


static int len_ext_prop(struct usb_configuration *c, int interface)
{
	struct usb_function *f;
	struct usb_os_desc *d;
	int j, res;

	res = 10; /* header length */
	f = c->interface[interface];
	for (j = 0; j < f->os_desc_n; ++j) {
		if (interface != f->os_desc_table[j].if_id)
			continue;
		d = f->os_desc_table[j].os_desc;
		if (d)
			return min(res + d->ext_prop_len, 4096);
	}
	return res;
}


static u8 encode_bMaxPower(enum usb_device_speed speed,
		struct usb_configuration *c)
{
	unsigned val;

	if (c->MaxPower || (c->bmAttributes & USB_CONFIG_ATT_SELFPOWER))
		val = c->MaxPower;
	else
		val = CONFIG_USB_GADGET_VBUS_DRAW;
	if (!val)
		return 0;
	if (speed < USB_SPEED_SUPER)
		return min(val, 500U) / 2;
	else
		/*
		 * USB 3.x supports up to 900mA, but since 900 isn't divisible
		 * by 8 the integral division will effectively cap to 896mA.
		 */
		return min(val, 900U) / 8;
}


static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req)
{
	struct usb_composite_dev *cdev;

	if (req->status || req->actual != req->length)
		DBG((struct usb_composite_dev *) ep->driver_data,
				"setup complete --> %d, %d/%d\n",
				req->status, req->actual, req->length);

	/*
	 * REVIST The same ep0 requests are shared with function drivers
	 * so they don't have to maintain the same ->complete() stubs.
	 *
	 * Because of that, we need to check for the validity of ->context
	 * here, even though we know we've set it to something useful.
	 */
	if (!req->context)
		return;

	cdev = req->context;

	if (cdev->req == req)
		cdev->setup_pending = false;
	else if (cdev->os_desc_req == req)
		cdev->os_desc_pending = false;
	else
		WARN(1, "unknown request %p\n", req);
}


static int count_ext_compat(struct usb_configuration *c)
{
	int i, res;

	res = 0;
	for (i = 0; i < c->next_interface_id; ++i) {
		struct usb_function *f;
		int j;

		f = c->interface[i];
		for (j = 0; j < f->os_desc_n; ++j) {
			struct usb_os_desc *d;

			if (i != f->os_desc_table[j].if_id)
				continue;
			d = f->os_desc_table[j].os_desc;
			if (d && d->ext_compat_id)
				++res;
		}
	}
	BUG_ON(res > 255);
	return res;
}


static struct usb_gadget_string_container *copy_gadget_strings(
		struct usb_gadget_strings **sp, unsigned n_gstrings,
		unsigned n_strings)
{
	struct usb_gadget_string_container *uc;
	struct usb_gadget_strings **gs_array;
	struct usb_gadget_strings *gs;
	struct usb_string *s;
	unsigned mem;
	unsigned n_gs;
	unsigned n_s;
	void *stash;

	mem = sizeof(*uc);
	mem += sizeof(void *) * (n_gstrings + 1);
	mem += sizeof(struct usb_gadget_strings) * n_gstrings;
	mem += sizeof(struct usb_string) * (n_strings + 1) * (n_gstrings);
	uc = kmalloc(mem, GFP_KERNEL);
	if (!uc)
		return ERR_PTR(-ENOMEM);
	gs_array = get_containers_gs(uc);
	stash = uc->stash;
	stash += sizeof(void *) * (n_gstrings + 1);
	for (n_gs = 0; n_gs < n_gstrings; n_gs++) {
		struct usb_string *org_s;

		gs_array[n_gs] = stash;
		gs = gs_array[n_gs];
		stash += sizeof(struct usb_gadget_strings);
		gs->language = sp[n_gs]->language;
		gs->strings = stash;
		org_s = sp[n_gs]->strings;

		for (n_s = 0; n_s < n_strings; n_s++) {
			s = stash;
			stash += sizeof(struct usb_string);
			if (org_s->s)
				s->s = org_s->s;
			else
				s->s = "";
			org_s++;
		}
		s = stash;
		s->s = NULL;
		stash += sizeof(struct usb_string);

	}
	gs_array[n_gs] = NULL;
	return uc;
}


static void __composite_disconnect(struct usb_gadget *gadget)
{
	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
	unsigned long			flags;

	/* REVISIT:  should we have config and device level
	 * disconnect callbacks?
	 */
	spin_lock_irqsave(&cdev->lock, flags);
	cdev->suspended = 0;
	if (cdev->config)
		reset_config(cdev);
	if (cdev->driver->disconnect)
		cdev->driver->disconnect(cdev);
	spin_unlock_irqrestore(&cdev->lock, flags);
}


static int composite_bind(struct usb_gadget *gadget,
		struct usb_gadget_driver *gdriver)
{
	struct usb_composite_dev	*cdev;
	struct usb_composite_driver	*composite = to_cdriver(gdriver);
	int				status = -ENOMEM;

	cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
	if (!cdev)
		return status;

	spin_lock_init(&cdev->lock);
	cdev->gadget = gadget;
	set_gadget_data(gadget, cdev);
	INIT_LIST_HEAD(&cdev->configs);
	INIT_LIST_HEAD(&cdev->gstrings);

	status = composite_dev_prepare(composite, cdev);
	if (status)
		goto fail;

	/* composite gadget needs to assign strings for whole device (like
	 * serial number), register function drivers, potentially update
	 * power state and consumption, etc
	 */
	status = composite->bind(cdev);
	if (status < 0)
		goto fail;

	if (cdev->use_os_string) {
		status = composite_os_desc_req_prepare(cdev, gadget->ep0);
		if (status)
			goto fail;
	}

	update_unchanged_dev_desc(&cdev->desc, composite->dev);

	/* has userspace failed to provide a serial number? */
	if (composite->needs_serial && !cdev->desc.iSerialNumber)
		WARNING(cdev, "userspace failed to provide iSerialNumber\n");

	INFO(cdev, "%s ready\n", composite->name);
	return 0;

fail:
	__composite_unbind(gadget, false);
	return status;
}


int usb_string_ids_n(struct usb_composite_dev *c, unsigned n)
{
	unsigned next = c->next_string_id;
	if (unlikely(n > 254 || (unsigned)next + n > 254))
		return -ENODEV;
	c->next_string_id += n;
	return next + 1;
}


int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str)
{
	int next = cdev->next_string_id;

	for (; str->s; ++str) {
		if (unlikely(next >= 254))
			return -ENODEV;
		str->id = ++next;
	}

	cdev->next_string_id = next;

	return 0;
}


static void reset_config(struct usb_composite_dev *cdev)
{
	struct usb_function		*f;

	DBG(cdev, "reset config\n");

	list_for_each_entry(f, &cdev->config->functions, list) {
		if (f->disable)
			f->disable(f);

		bitmap_zero(f->endpoints, 32);
	}
	cdev->config = NULL;
	cdev->delayed_status = 0;
}


static ssize_t suspended_show(struct device *dev, struct device_attribute *attr,
			      char *buf)
{
	struct usb_gadget *gadget = dev_to_usb_gadget(dev);
	struct usb_composite_dev *cdev = get_gadget_data(gadget);

	return sprintf(buf, "%d\n", cdev->suspended);
}


static int bos_desc(struct usb_composite_dev *cdev)
{
	struct usb_ext_cap_descriptor	*usb_ext;
	struct usb_dcd_config_params	dcd_config_params;
	struct usb_bos_descriptor	*bos = cdev->req->buf;
	unsigned int			besl = 0;

	bos->bLength = USB_DT_BOS_SIZE;
	bos->bDescriptorType = USB_DT_BOS;

	bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE);
	bos->bNumDeviceCaps = 0;

	/* Get Controller configuration */
	if (cdev->gadget->ops->get_config_params) {
		cdev->gadget->ops->get_config_params(cdev->gadget,
						     &dcd_config_params);
	} else {
		dcd_config_params.besl_baseline =
			USB_DEFAULT_BESL_UNSPECIFIED;
		dcd_config_params.besl_deep =
			USB_DEFAULT_BESL_UNSPECIFIED;
		dcd_config_params.bU1devExitLat =
			USB_DEFAULT_U1_DEV_EXIT_LAT;
		dcd_config_params.bU2DevExitLat =
			cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT);
	}

	if (dcd_config_params.besl_baseline != USB_DEFAULT_BESL_UNSPECIFIED)
		besl = USB_BESL_BASELINE_VALID |
			USB_SET_BESL_BASELINE(dcd_config_params.besl_baseline);

	if (dcd_config_params.besl_deep != USB_DEFAULT_BESL_UNSPECIFIED)
		besl |= USB_BESL_DEEP_VALID |
			USB_SET_BESL_DEEP(dcd_config_params.besl_deep);

	/*
	 * A SuperSpeed device shall include the USB2.0 extension descriptor
	 * and shall support LPM when operating in USB2.0 HS mode.
	 */
	usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
	bos->bNumDeviceCaps++;
	le16_add_cpu(&bos->wTotalLength, USB_DT_USB_EXT_CAP_SIZE);
	usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE;
	usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
	usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT;
	usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT |
					    USB_BESL_SUPPORT | besl);

	/*
	 * The Superspeed USB Capability descriptor shall be implemented by all
	 * SuperSpeed devices.
	 */
	if (gadget_is_superspeed(cdev->gadget)) {
		struct usb_ss_cap_descriptor *ss_cap;

		ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
		bos->bNumDeviceCaps++;
		le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE);
		ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE;
		ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
		ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE;
		ss_cap->bmAttributes = 0; /* LTM is not supported yet */
		ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION |
						      USB_FULL_SPEED_OPERATION |
						      USB_HIGH_SPEED_OPERATION |
						      USB_5GBPS_OPERATION);
		ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION;
		ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat;
		ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat;
	}

	/* The SuperSpeedPlus USB Device Capability descriptor */
	if (gadget_is_superspeed_plus(cdev->gadget)) {
		struct usb_ssp_cap_descriptor *ssp_cap;
		u8 ssac = 1;
		u8 ssic;
		int i;

		if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x2)
			ssac = 3;

		/*
		 * Paired RX and TX sublink speed attributes share
		 * the same SSID.
		 */
		ssic = (ssac + 1) / 2 - 1;

		ssp_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength);
		bos->bNumDeviceCaps++;

		le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SSP_CAP_SIZE(ssac));
		ssp_cap->bLength = USB_DT_USB_SSP_CAP_SIZE(ssac);
		ssp_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY;
		ssp_cap->bDevCapabilityType = USB_SSP_CAP_TYPE;
		ssp_cap->bReserved = 0;
		ssp_cap->wReserved = 0;

		ssp_cap->bmAttributes =
			cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_ATTRIBS, ssac) |
				    FIELD_PREP(USB_SSP_SUBLINK_SPEED_IDS, ssic));

		ssp_cap->wFunctionalitySupport =
			cpu_to_le16(FIELD_PREP(USB_SSP_MIN_SUBLINK_SPEED_ATTRIBUTE_ID, 0) |
				    FIELD_PREP(USB_SSP_MIN_RX_LANE_COUNT, 1) |
				    FIELD_PREP(USB_SSP_MIN_TX_LANE_COUNT, 1));

		/*
		 * Use 1 SSID if the gadget supports up to gen2x1 or not
		 * specified:
		 * - SSID 0 for symmetric RX/TX sublink speed of 10 Gbps.
		 *
		 * Use 1 SSID if the gadget supports up to gen1x2:
		 * - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps.
		 *
		 * Use 2 SSIDs if the gadget supports up to gen2x2:
		 * - SSID 0 for symmetric RX/TX sublink speed of 5 Gbps.
		 * - SSID 1 for symmetric RX/TX sublink speed of 10 Gbps.
		 */
		for (i = 0; i < ssac + 1; i++) {
			u8 ssid;
			u8 mantissa;
			u8 type;

			ssid = i >> 1;

			if (cdev->gadget->max_ssp_rate == USB_SSP_GEN_2x1 ||
			    cdev->gadget->max_ssp_rate == USB_SSP_GEN_UNKNOWN)
				mantissa = 10;
			else
				mantissa = 5 << ssid;

			if (i % 2)
				type = USB_SSP_SUBLINK_SPEED_ST_SYM_TX;
			else
				type = USB_SSP_SUBLINK_SPEED_ST_SYM_RX;

			ssp_cap->bmSublinkSpeedAttr[i] =
				cpu_to_le32(FIELD_PREP(USB_SSP_SUBLINK_SPEED_SSID, ssid) |
					    FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSE,
						       USB_SSP_SUBLINK_SPEED_LSE_GBPS) |
					    FIELD_PREP(USB_SSP_SUBLINK_SPEED_ST, type) |
					    FIELD_PREP(USB_SSP_SUBLINK_SPEED_LP,
						       USB_SSP_SUBLINK_SPEED_LP_SSP) |
					    FIELD_PREP(USB_SSP_SUBLINK_SPEED_LSM, mantissa));
		}
	}

	return le16_to_cpu(bos->wTotalLength);
}


static int set_config(struct usb_composite_dev *cdev,
		const struct usb_ctrlrequest *ctrl, unsigned number)
{
	struct usb_gadget	*gadget = cdev->gadget;
	struct usb_configuration *c = NULL;
	int			result = -EINVAL;
	unsigned		power = gadget_is_otg(gadget) ? 8 : 100;
	int			tmp;

	if (number) {
		list_for_each_entry(c, &cdev->configs, list) {
			if (c->bConfigurationValue == number) {
				/*
				 * We disable the FDs of the previous
				 * configuration only if the new configuration
				 * is a valid one
				 */
				if (cdev->config)
					reset_config(cdev);
				result = 0;
				break;
			}
		}
		if (result < 0)
			goto done;
	} else { /* Zero configuration value - need to reset the config */
		if (cdev->config)
			reset_config(cdev);
		result = 0;
	}

	DBG(cdev, "%s config #%d: %s\n",
	    usb_speed_string(gadget->speed),
	    number, c ? c->label : "unconfigured");

	if (!c)
		goto done;

	usb_gadget_set_state(gadget, USB_STATE_CONFIGURED);
	cdev->config = c;

	/* Initialize all interfaces by setting them to altsetting zero. */
	for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {
		struct usb_function	*f = c->interface[tmp];
		struct usb_descriptor_header **descriptors;

		if (!f)
			break;

		/*
		 * Record which endpoints are used by the function. This is used
		 * to dispatch control requests targeted at that endpoint to the
		 * function's setup callback instead of the current
		 * configuration's setup callback.
		 */
		descriptors = function_descriptors(f, gadget->speed);

		for (; *descriptors; ++descriptors) {
			struct usb_endpoint_descriptor *ep;
			int addr;

			if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT)
				continue;

			ep = (struct usb_endpoint_descriptor *)*descriptors;
			addr = ((ep->bEndpointAddress & 0x80) >> 3)
			     |  (ep->bEndpointAddress & 0x0f);
			set_bit(addr, f->endpoints);
		}

		result = f->set_alt(f, tmp, 0);
		if (result < 0) {
			DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n",
					tmp, f->name, f, result);

			reset_config(cdev);
			goto done;
		}

		if (result == USB_GADGET_DELAYED_STATUS) {
			DBG(cdev,
			 "%s: interface %d (%s) requested delayed status\n",
					__func__, tmp, f->name);
			cdev->delayed_status++;
			DBG(cdev, "delayed_status count %d\n",
					cdev->delayed_status);
		}
	}

	/* when we return, be sure our power usage is valid */
	if (c->MaxPower || (c->bmAttributes & USB_CONFIG_ATT_SELFPOWER))
		power = c->MaxPower;
	else
		power = CONFIG_USB_GADGET_VBUS_DRAW;

	if (gadget->speed < USB_SPEED_SUPER)
		power = min(power, 500U);
	else
		power = min(power, 900U);
done:
	if (power <= USB_SELF_POWER_VBUS_MAX_DRAW)
		usb_gadget_set_selfpowered(gadget);
	else
		usb_gadget_clear_selfpowered(gadget);

	usb_gadget_vbus_draw(gadget, power);
	if (result >= 0 && cdev->delayed_status)
		result = USB_GADGET_DELAYED_STATUS;
	return result;
}


static int fill_ext_compat(struct usb_configuration *c, u8 *buf)
{
	int i, count;

	count = 16;
	buf += 16;
	for (i = 0; i < c->next_interface_id; ++i) {
		struct usb_function *f;
		int j;

		f = c->interface[i];
		for (j = 0; j < f->os_desc_n; ++j) {
			struct usb_os_desc *d;

			if (i != f->os_desc_table[j].if_id)
				continue;
			d = f->os_desc_table[j].os_desc;
			if (d && d->ext_compat_id) {
				*buf++ = i;
				*buf++ = 0x01;
				memcpy(buf, d->ext_compat_id, 16);
				buf += 22;
			} else {
				++buf;
				*buf = 0x01;
				buf += 23;
			}
			count += 24;
			if (count + 24 >= USB_COMP_EP0_OS_DESC_BUFSIZ)
				return count;
		}
	}

	return count;
}


static int composite_ep0_queue(struct usb_composite_dev *cdev,
		struct usb_request *req, gfp_t gfp_flags)
{
	int ret;

	ret = usb_ep_queue(cdev->gadget->ep0, req, gfp_flags);
	if (ret == 0) {
		if (cdev->req == req)
			cdev->setup_pending = true;
		else if (cdev->os_desc_req == req)
			cdev->os_desc_pending = true;
		else
			WARN(1, "unknown request %p\n", req);
	}

	return ret;
}


static int lookup_string(
	struct usb_gadget_strings	**sp,
	void				*buf,
	u16				language,
	int				id
)
{
	struct usb_gadget_strings	*s;
	int				value;

	while (*sp) {
		s = *sp++;
		if (s->language != language)
			continue;
		value = usb_gadget_get_string(s, id, buf);
		if (value > 0)
			return value;
	}
	return -EINVAL;
}


static int fill_ext_prop(struct usb_configuration *c, int interface, u8 *buf)
{
	struct usb_function *f;
	struct usb_os_desc *d;
	struct usb_os_desc_ext_prop *ext_prop;
	int j, count, n, ret;

	f = c->interface[interface];
	count = 10; /* header length */
	buf += 10;
	for (j = 0; j < f->os_desc_n; ++j) {
		if (interface != f->os_desc_table[j].if_id)
			continue;
		d = f->os_desc_table[j].os_desc;
		if (d)
			list_for_each_entry(ext_prop, &d->ext_prop, entry) {
				n = ext_prop->data_len +
					ext_prop->name_len + 14;
				if (count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ)
					return count;
				usb_ext_prop_put_size(buf, n);
				usb_ext_prop_put_type(buf, ext_prop->type);
				ret = usb_ext_prop_put_name(buf, ext_prop->name,
							    ext_prop->name_len);
				if (ret < 0)
					return ret;
				switch (ext_prop->type) {
				case USB_EXT_PROP_UNICODE:
				case USB_EXT_PROP_UNICODE_ENV:
				case USB_EXT_PROP_UNICODE_LINK:
					usb_ext_prop_put_unicode(buf, ret,
							 ext_prop->data,
							 ext_prop->data_len);
					break;
				case USB_EXT_PROP_BINARY:
					usb_ext_prop_put_binary(buf, ret,
							ext_prop->data,
							ext_prop->data_len);
					break;
				case USB_EXT_PROP_LE32:
					/* not implemented */
				case USB_EXT_PROP_BE32:
					/* not implemented */
				default:
					return -EINVAL;
				}
				buf += n;
				count += n;
			}
	}

	return count;
}


void composite_disconnect(struct usb_gadget *gadget)
{
	usb_gadget_vbus_draw(gadget, 0);
	__composite_disconnect(gadget);
}


int usb_composite_probe(struct usb_composite_driver *driver)
{
	struct usb_gadget_driver *gadget_driver;

	if (!driver || !driver->dev || !driver->bind)
		return -EINVAL;

	if (!driver->name)
		driver->name = "composite";

	driver->gadget_driver = composite_driver_template;
	gadget_driver = &driver->gadget_driver;

	gadget_driver->function =  (char *) driver->name;
	gadget_driver->driver.name = driver->name;
	gadget_driver->max_speed = driver->max_speed;

	return usb_gadget_probe_driver(gadget_driver);
}


int usb_add_function(struct usb_configuration *config,
		struct usb_function *function)
{
	int	value = -EINVAL;

	DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
			function->name, function,
			config->label, config);

	if (!function->set_alt || !function->disable)
		goto done;

	function->config = config;
	list_add_tail(&function->list, &config->functions);

	if (function->bind_deactivated) {
		value = usb_function_deactivate(function);
		if (value)
			goto done;
	}

	/* REVISIT *require* function->bind? */
	if (function->bind) {
		value = function->bind(config, function);
		if (value < 0) {
			list_del(&function->list);
			function->config = NULL;
		}
	} else
		value = 0;

	/* We allow configurations that don't work at both speeds.
	 * If we run into a lowspeed Linux system, treat it the same
	 * as full speed ... it's the function drivers that will need
	 * to avoid bulk and ISO transfers.
	 */
	if (!config->fullspeed && function->fs_descriptors)
		config->fullspeed = true;
	if (!config->highspeed && function->hs_descriptors)
		config->highspeed = true;
	if (!config->superspeed && function->ss_descriptors)
		config->superspeed = true;
	if (!config->superspeed_plus && function->ssp_descriptors)
		config->superspeed_plus = true;

done:
	if (value)
		DBG(config->cdev, "adding '%s'/%p --> %d\n",
				function->name, function, value);
	return value;
}


struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev,
		struct usb_gadget_strings **sp, unsigned n_strings)
{
	struct usb_gadget_string_container *uc;
	struct usb_gadget_strings **n_gs;
	unsigned n_gstrings = 0;
	unsigned i;
	int ret;

	for (i = 0; sp[i]; i++)
		n_gstrings++;

	if (!n_gstrings)
		return ERR_PTR(-EINVAL);

	uc = copy_gadget_strings(sp, n_gstrings, n_strings);
	if (IS_ERR(uc))
		return ERR_CAST(uc);

	n_gs = get_containers_gs(uc);
	ret = usb_string_ids_tab(cdev, n_gs[0]->strings);
	if (ret)
		goto err;

	for (i = 1; i < n_gstrings; i++) {
		struct usb_string *m_s;
		struct usb_string *s;
		unsigned n;

		m_s = n_gs[0]->strings;
		s = n_gs[i]->strings;
		for (n = 0; n < n_strings; n++) {
			s->id = m_s->id;
			s++;
			m_s++;
		}
	}
	list_add_tail(&uc->list, &cdev->gstrings);
	return n_gs[0]->strings;
err:
	kfree(uc);
	return ERR_PTR(ret);
}


int usb_add_config(struct usb_composite_dev *cdev,
		struct usb_configuration *config,
		int (*bind)(struct usb_configuration *))
{
	int				status = -EINVAL;

	if (!bind)
		goto done;

	DBG(cdev, "adding config #%u '%s'/%p\n",
			config->bConfigurationValue,
			config->label, config);

	status = usb_add_config_only(cdev, config);
	if (status)
		goto done;

	status = bind(config);
	if (status < 0) {
		while (!list_empty(&config->functions)) {
			struct usb_function		*f;

			f = list_first_entry(&config->functions,
					struct usb_function, list);
			list_del(&f->list);
			if (f->unbind) {
				DBG(cdev, "unbind function '%s'/%p\n",
					f->name, f);
				f->unbind(config, f);
				/* may free memory for "f" */
			}
		}
		list_del(&config->list);
		config->cdev = NULL;
	} else {
		unsigned	i;

		DBG(cdev, "cfg %d/%p speeds:%s%s%s%s\n",
			config->bConfigurationValue, config,
			config->superspeed_plus ? " superplus" : "",
			config->superspeed ? " super" : "",
			config->highspeed ? " high" : "",
			config->fullspeed
				? (gadget_is_dualspeed(cdev->gadget)
					? " full"
					: " full/low")
				: "");

		for (i = 0; i < MAX_CONFIG_INTERFACES; i++) {
			struct usb_function	*f = config->interface[i];

			if (!f)
				continue;
			DBG(cdev, "  interface %d = %s/%p\n",
				i, f->name, f);
		}
	}

	/* set_alt(), or next bind(), sets up ep->claimed as needed */
	usb_ep_autoconfig_reset(cdev->gadget);

done:
	if (status)
		DBG(cdev, "added config '%s'/%u --> %d\n", config->label,
				config->bConfigurationValue, status);
	return status;
}


void usb_composite_setup_continue(struct usb_composite_dev *cdev)
{
	int			value;
	struct usb_request	*req = cdev->req;
	unsigned long		flags;

	DBG(cdev, "%s\n", __func__);
	spin_lock_irqsave(&cdev->lock, flags);

	if (cdev->delayed_status == 0) {
		WARN(cdev, "%s: Unexpected call\n", __func__);

	} else if (--cdev->delayed_status == 0) {
		DBG(cdev, "%s: Completing delayed status\n", __func__);
		req->length = 0;
		req->context = cdev;
		value = composite_ep0_queue(cdev, req, GFP_ATOMIC);
		if (value < 0) {
			DBG(cdev, "ep_queue --> %d\n", value);
			req->status = 0;
			composite_setup_complete(cdev->gadget->ep0, req);
		}
	}

	spin_unlock_irqrestore(&cdev->lock, flags);
}


static void remove_config(struct usb_composite_dev *cdev,
			      struct usb_configuration *config)
{
	while (!list_empty(&config->functions)) {
		struct usb_function		*f;

		f = list_first_entry(&config->functions,
				struct usb_function, list);

		usb_remove_function(config, f);
	}
	list_del(&config->list);
	if (config->unbind) {
		DBG(cdev, "unbind config '%s'/%p\n", config->label, config);
		config->unbind(config);
			/* may free memory for "c" */
	}
}


current_block(
    oparg_T	*oap,
    long	count,
    int		include,	// TRUE == include white space
    int		what,		// '(', '{', etc.
    int		other)		// ')', '}', etc.
{
    pos_T	old_pos;
    pos_T	*pos = NULL;
    pos_T	start_pos;
    pos_T	*end_pos;
    pos_T	old_start, old_end;
    char_u	*save_cpo;
    int		sol = FALSE;		// '{' at start of line

    old_pos = curwin->w_cursor;
    old_end = curwin->w_cursor;		// remember where we started
    old_start = old_end;

    /*
     * If we start on '(', '{', ')', '}', etc., use the whole block inclusive.
     */
    if (!VIsual_active || EQUAL_POS(VIsual, curwin->w_cursor))
    {
	setpcmark();
	if (what == '{')		// ignore indent
	    while (inindent(1))
		if (inc_cursor() != 0)
		    break;
	if (gchar_cursor() == what)
	    // cursor on '(' or '{', move cursor just after it
	    ++curwin->w_cursor.col;
    }
    else if (LT_POS(VIsual, curwin->w_cursor))
    {
	old_start = VIsual;
	curwin->w_cursor = VIsual;	    // cursor at low end of Visual
    }
    else
	old_end = VIsual;

    /*
     * Search backwards for unclosed '(', '{', etc..
     * Put this position in start_pos.
     * Ignore quotes here.  Keep the "M" flag in 'cpo', as that is what the
     * user wants.
     */
    save_cpo = p_cpo;
    p_cpo = (char_u *)(vim_strchr(p_cpo, CPO_MATCHBSL) != NULL ? "%M" : "%");
    if ((pos = findmatch(NULL, what)) != NULL)
    {
	while (count-- > 0)
	{
	    if ((pos = findmatch(NULL, what)) == NULL)
		break;
	    curwin->w_cursor = *pos;
	    start_pos = *pos;   // the findmatch for end_pos will overwrite *pos
	}
    }
    else
    {
	while (count-- > 0)
	{
	    if ((pos = findmatchlimit(NULL, what, FM_FORWARD, 0)) == NULL)
		break;
	    curwin->w_cursor = *pos;
	    start_pos = *pos;   // the findmatch for end_pos will overwrite *pos
	}
    }
    p_cpo = save_cpo;

    /*
     * Search for matching ')', '}', etc.
     * Put this position in curwin->w_cursor.
     */
    if (pos == NULL || (end_pos = findmatch(NULL, other)) == NULL)
    {
	curwin->w_cursor = old_pos;
	return FAIL;
    }
    curwin->w_cursor = *end_pos;

    /*
     * Try to exclude the '(', '{', ')', '}', etc. when "include" is FALSE.
     * If the ending '}', ')' or ']' is only preceded by indent, skip that
     * indent.  But only if the resulting area is not smaller than what we
     * started with.
     */
    while (!include)
    {
	incl(&start_pos);
	sol = (curwin->w_cursor.col == 0);
	decl(&curwin->w_cursor);
	while (inindent(1))
	{
	    sol = TRUE;
	    if (decl(&curwin->w_cursor) != 0)
		break;
	}

	/*
	 * In Visual mode, when the resulting area is not bigger than what we
	 * started with, extend it to the next block, and then exclude again.
	 */
	if (!LT_POS(start_pos, old_start) && !LT_POS(old_end, curwin->w_cursor)
		&& VIsual_active)
	{
	    curwin->w_cursor = old_start;
	    decl(&curwin->w_cursor);
	    if ((pos = findmatch(NULL, what)) == NULL)
	    {
		curwin->w_cursor = old_pos;
		return FAIL;
	    }
	    start_pos = *pos;
	    curwin->w_cursor = *pos;
	    if ((end_pos = findmatch(NULL, other)) == NULL)
	    {
		curwin->w_cursor = old_pos;
		return FAIL;
	    }
	    curwin->w_cursor = *end_pos;
	}
	else
	    break;
    }

    if (VIsual_active)
    {
	if (*p_sel == 'e')
	    inc(&curwin->w_cursor);
	if (sol && gchar_cursor() != NUL)
	    inc(&curwin->w_cursor);	// include the line break
	VIsual = start_pos;
	VIsual_mode = 'v';
	redraw_curbuf_later(INVERTED);	// update the inversion
	showmode();
    }
    else
    {
	oap->start = start_pos;
	oap->motion_type = MCHAR;
	oap->inclusive = FALSE;
	if (sol)
	    incl(&curwin->w_cursor);
	else if (LTOREQ_POS(start_pos, curwin->w_cursor))
	    // Include the character under the cursor.
	    oap->inclusive = TRUE;
	else
	    // End is before the start (no text in between <>, [], etc.): don't
	    // operate on any text.
	    curwin->w_cursor = start_pos;
    }

    return OK;
}

patch 8.2.4925: trailing backslash may cause reading past end of line

Problem:    Trailing backslash may cause reading past end of line.
Solution:   Check for NUL after backslash.


static void tipc_crypto_work_tx(struct work_struct *work)
{
	struct delayed_work *dwork = to_delayed_work(work);
	struct tipc_crypto *tx = container_of(dwork, struct tipc_crypto, work);
	struct tipc_aead_key *skey = NULL;
	struct tipc_key key = tx->key;
	struct tipc_aead *aead;
	int rc = -ENOMEM;

	if (unlikely(key.pending))
		goto resched;

	/* Take current key as a template */
	rcu_read_lock();
	aead = rcu_dereference(tx->aead[key.active ?: KEY_MASTER]);
	if (unlikely(!aead)) {
		rcu_read_unlock();
		/* At least one key should exist for securing */
		return;
	}

	/* Lets duplicate it first */
	skey = kmemdup(aead->key, tipc_aead_key_size(aead->key), GFP_ATOMIC);
	rcu_read_unlock();

	/* Now, generate new key, initiate & distribute it */
	if (likely(skey)) {
		rc = tipc_aead_key_generate(skey) ?:
		     tipc_crypto_key_init(tx, skey, PER_NODE_KEY, false);
		if (likely(rc > 0))
			rc = tipc_crypto_key_distr(tx, rc, NULL);
		kfree_sensitive(skey);
	}

	if (unlikely(rc))
		pr_warn_ratelimited("%s: rekeying returns %d\n", tx->name, rc);

resched:
	/* Re-schedule rekeying if any */
	tipc_crypto_rekeying_sched(tx, false, 0);
}

tipc: fix size validations for the MSG_CRYPTO type

The function tipc_crypto_key_rcv is used to parse MSG_CRYPTO messages
to receive keys from other nodes in the cluster in order to decrypt any
further messages from them.
This patch verifies that any supplied sizes in the message body are
valid for the received message.

Fixes: 1ef6f7c9390f ("tipc: add automatic session key exchange")
Signed-off-by: Max VA <maxv@sentinelone.com>
Acked-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>


static void tipc_aead_free(struct rcu_head *rp)
{
	struct tipc_aead *aead = container_of(rp, struct tipc_aead, rcu);
	struct tipc_tfm *tfm_entry, *head, *tmp;

	if (aead->cloned) {
		tipc_aead_put(aead->cloned);
	} else {
		head = *get_cpu_ptr(aead->tfm_entry);
		put_cpu_ptr(aead->tfm_entry);
		list_for_each_entry_safe(tfm_entry, tmp, &head->list, list) {
			crypto_free_aead(tfm_entry->tfm);
			list_del(&tfm_entry->list);
			kfree(tfm_entry);
		}
		/* Free the head */
		crypto_free_aead(head->tfm);
		list_del(&head->list);
		kfree(head);
	}
	free_percpu(aead->tfm_entry);
	kfree_sensitive(aead->key);
	kfree(aead);
}


static inline int tipc_ehdr_size(struct tipc_ehdr *ehdr)
{
	return (ehdr->user != LINK_CONFIG) ? EHDR_SIZE : EHDR_CFG_SIZE;
}


static void tipc_aead_users_inc(struct tipc_aead __rcu *aead, int lim)
{
	struct tipc_aead *tmp;

	rcu_read_lock();
	tmp = rcu_dereference(aead);
	if (tmp)
		atomic_add_unless(&tmp->users, 1, lim);
	rcu_read_unlock();
}


static int tipc_crypto_key_revoke(struct net *net, u8 tx_key)
{
	struct tipc_crypto *tx = tipc_net(net)->crypto_tx;
	struct tipc_key key;

	spin_lock(&tx->lock);
	key = tx->key;
	WARN_ON(!key.active || tx_key != key.active);

	/* Free the active key */
	tipc_crypto_key_set_state(tx, key.passive, 0, key.pending);
	tipc_crypto_key_detach(tx->aead[key.active], &tx->lock);
	spin_unlock(&tx->lock);

	pr_warn("%s: key is revoked\n", tx->name);
	return -EKEYREVOKED;
}


static int tipc_aead_decrypt(struct net *net, struct tipc_aead *aead,
			     struct sk_buff *skb, struct tipc_bearer *b)
{
	struct tipc_crypto_rx_ctx *rx_ctx;
	struct aead_request *req;
	struct crypto_aead *tfm;
	struct sk_buff *unused;
	struct scatterlist *sg;
	struct tipc_ehdr *ehdr;
	int ehsz, nsg, rc;
	void *ctx;
	u32 salt;
	u8 *iv;

	if (unlikely(!aead))
		return -ENOKEY;

	nsg = skb_cow_data(skb, 0, &unused);
	if (unlikely(nsg < 0)) {
		pr_err("RX: skb_cow_data() returned %d\n", nsg);
		return nsg;
	}

	/* Allocate memory for the AEAD operation */
	tfm = tipc_aead_tfm_next(aead);
	ctx = tipc_aead_mem_alloc(tfm, sizeof(*rx_ctx), &iv, &req, &sg, nsg);
	if (unlikely(!ctx))
		return -ENOMEM;
	TIPC_SKB_CB(skb)->crypto_ctx = ctx;

	/* Map skb to the sg lists */
	sg_init_table(sg, nsg);
	rc = skb_to_sgvec(skb, sg, 0, skb->len);
	if (unlikely(rc < 0)) {
		pr_err("RX: skb_to_sgvec() returned %d, nsg %d\n", rc, nsg);
		goto exit;
	}

	/* Reconstruct IV: */
	ehdr = (struct tipc_ehdr *)skb->data;
	salt = aead->salt;
	if (aead->mode == CLUSTER_KEY)
		salt ^= __be32_to_cpu(ehdr->addr);
	else if (ehdr->destined)
		salt ^= tipc_own_addr(net);
	memcpy(iv, &salt, 4);
	memcpy(iv + 4, (u8 *)&ehdr->seqno, 8);

	/* Prepare request */
	ehsz = tipc_ehdr_size(ehdr);
	aead_request_set_tfm(req, tfm);
	aead_request_set_ad(req, ehsz);
	aead_request_set_crypt(req, sg, sg, skb->len - ehsz, iv);

	/* Set callback function & data */
	aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
				  tipc_aead_decrypt_done, skb);
	rx_ctx = (struct tipc_crypto_rx_ctx *)ctx;
	rx_ctx->aead = aead;
	rx_ctx->bearer = b;

	/* Hold bearer */
	if (unlikely(!tipc_bearer_hold(b))) {
		rc = -ENODEV;
		goto exit;
	}

	/* Now, do decrypt */
	rc = crypto_aead_decrypt(req);
	if (rc == -EINPROGRESS || rc == -EBUSY)
		return rc;

	tipc_bearer_put(b);

exit:
	kfree(ctx);
	TIPC_SKB_CB(skb)->crypto_ctx = NULL;
	return rc;
}


static int tipc_aead_users(struct tipc_aead __rcu *aead)
{
	struct tipc_aead *tmp;
	int users = 0;

	rcu_read_lock();
	tmp = rcu_dereference(aead);
	if (tmp)
		users = atomic_read(&tmp->users);
	rcu_read_unlock();

	return users;
}


int tipc_crypto_key_distr(struct tipc_crypto *tx, u8 key,
			  struct tipc_node *dest)
{
	struct tipc_aead *aead;
	u32 dnode = tipc_node_get_addr(dest);
	int rc = -ENOKEY;

	if (!sysctl_tipc_key_exchange_enabled)
		return 0;

	if (key) {
		rcu_read_lock();
		aead = tipc_aead_get(tx->aead[key]);
		if (likely(aead)) {
			rc = tipc_crypto_key_xmit(tx->net, aead->key,
						  aead->gen, aead->mode,
						  dnode);
			tipc_aead_put(aead);
		}
		rcu_read_unlock();
	}

	return rc;
}


int tipc_crypto_start(struct tipc_crypto **crypto, struct net *net,
		      struct tipc_node *node)
{
	struct tipc_crypto *c;

	if (*crypto)
		return -EEXIST;

	/* Allocate crypto */
	c = kzalloc(sizeof(*c), GFP_ATOMIC);
	if (!c)
		return -ENOMEM;

	/* Allocate workqueue on TX */
	if (!node) {
		c->wq = alloc_ordered_workqueue("tipc_crypto", 0);
		if (!c->wq) {
			kfree(c);
			return -ENOMEM;
		}
	}

	/* Allocate statistic structure */
	c->stats = alloc_percpu_gfp(struct tipc_crypto_stats, GFP_ATOMIC);
	if (!c->stats) {
		if (c->wq)
			destroy_workqueue(c->wq);
		kfree_sensitive(c);
		return -ENOMEM;
	}

	c->flags = 0;
	c->net = net;
	c->node = node;
	get_random_bytes(&c->key_gen, 2);
	tipc_crypto_key_set_state(c, 0, 0, 0);
	atomic_set(&c->key_distr, 0);
	atomic_set(&c->peer_rx_active, 0);
	atomic64_set(&c->sndnxt, 0);
	c->timer1 = jiffies;
	c->timer2 = jiffies;
	c->rekeying_intv = TIPC_REKEYING_INTV_DEF;
	spin_lock_init(&c->lock);
	scnprintf(c->name, 48, "%s(%s)", (is_rx(c)) ? "RX" : "TX",
		  (is_rx(c)) ? tipc_node_get_id_str(c->node) :
			       tipc_own_id_string(c->net));

	if (is_rx(c))
		INIT_DELAYED_WORK(&c->work, tipc_crypto_work_rx);
	else
		INIT_DELAYED_WORK(&c->work, tipc_crypto_work_tx);

	*crypto = c;
	return 0;
}


static bool tipc_crypto_key_try_align(struct tipc_crypto *rx, u8 new_pending)
{
	struct tipc_aead *tmp1, *tmp2 = NULL;
	struct tipc_key key;
	bool aligned = false;
	u8 new_passive = 0;
	int x;

	spin_lock(&rx->lock);
	key = rx->key;
	if (key.pending == new_pending) {
		aligned = true;
		goto exit;
	}
	if (key.active)
		goto exit;
	if (!key.pending)
		goto exit;
	if (tipc_aead_users(rx->aead[key.pending]) > 0)
		goto exit;

	/* Try to "isolate" this pending key first */
	tmp1 = tipc_aead_rcu_ptr(rx->aead[key.pending], &rx->lock);
	if (!refcount_dec_if_one(&tmp1->refcnt))
		goto exit;
	rcu_assign_pointer(rx->aead[key.pending], NULL);

	/* Move passive key if any */
	if (key.passive) {
		tmp2 = rcu_replace_pointer(rx->aead[key.passive], tmp2, lockdep_is_held(&rx->lock));
		x = (key.passive - key.pending + new_pending) % KEY_MAX;
		new_passive = (x <= 0) ? x + KEY_MAX : x;
	}

	/* Re-allocate the key(s) */
	tipc_crypto_key_set_state(rx, new_passive, 0, new_pending);
	rcu_assign_pointer(rx->aead[new_pending], tmp1);
	if (new_passive)
		rcu_assign_pointer(rx->aead[new_passive], tmp2);
	refcount_set(&tmp1->refcnt, 1);
	aligned = true;
	pr_info_ratelimited("%s: key[%d] -> key[%d]\n", rx->name, key.pending,
			    new_pending);

exit:
	spin_unlock(&rx->lock);
	return aligned;
}


void tipc_crypto_msg_rcv(struct net *net, struct sk_buff *skb)
{
	struct tipc_crypto *rx;
	struct tipc_msg *hdr;

	if (unlikely(skb_linearize(skb)))
		goto exit;

	hdr = buf_msg(skb);
	rx = tipc_node_crypto_rx_by_addr(net, msg_prevnode(hdr));
	if (unlikely(!rx))
		goto exit;

	switch (msg_type(hdr)) {
	case KEY_DISTR_MSG:
		if (tipc_crypto_key_rcv(rx, hdr))
			goto exit;
		break;
	default:
		break;
	}

	tipc_node_put(rx->node);

exit:
	kfree_skb(skb);
}


static bool tipc_crypto_key_rcv(struct tipc_crypto *rx, struct tipc_msg *hdr)
{
	struct tipc_crypto *tx = tipc_net(rx->net)->crypto_tx;
	struct tipc_aead_key *skey = NULL;
	u16 key_gen = msg_key_gen(hdr);
	u16 size = msg_data_sz(hdr);
	u8 *data = msg_data(hdr);
	unsigned int keylen;

	/* Verify whether the size can exist in the packet */
	if (unlikely(size < sizeof(struct tipc_aead_key) + TIPC_AEAD_KEYLEN_MIN)) {
		pr_debug("%s: message data size is too small\n", rx->name);
		goto exit;
	}

	keylen = ntohl(*((__be32 *)(data + TIPC_AEAD_ALG_NAME)));

	/* Verify the supplied size values */
	if (unlikely(size != keylen + sizeof(struct tipc_aead_key) ||
		     keylen > TIPC_AEAD_KEY_SIZE_MAX)) {
		pr_debug("%s: invalid MSG_CRYPTO key size\n", rx->name);
		goto exit;
	}

	spin_lock(&rx->lock);
	if (unlikely(rx->skey || (key_gen == rx->key_gen && rx->key.keys))) {
		pr_err("%s: key existed <%p>, gen %d vs %d\n", rx->name,
		       rx->skey, key_gen, rx->key_gen);
		goto exit_unlock;
	}

	/* Allocate memory for the key */
	skey = kmalloc(size, GFP_ATOMIC);
	if (unlikely(!skey)) {
		pr_err("%s: unable to allocate memory for skey\n", rx->name);
		goto exit_unlock;
	}

	/* Copy key from msg data */
	skey->keylen = keylen;
	memcpy(skey->alg_name, data, TIPC_AEAD_ALG_NAME);
	memcpy(skey->key, data + TIPC_AEAD_ALG_NAME + sizeof(__be32),
	       skey->keylen);

	rx->key_gen = key_gen;
	rx->skey_mode = msg_key_mode(hdr);
	rx->skey = skey;
	rx->nokey = 0;
	mb(); /* for nokey flag */

exit_unlock:
	spin_unlock(&rx->lock);

exit:
	/* Schedule the key attaching on this crypto */
	if (likely(skey && queue_delayed_work(tx->wq, &rx->work, 0)))
		return true;

	return false;
}


bool tipc_ehdr_validate(struct sk_buff *skb)
{
	struct tipc_ehdr *ehdr;
	int ehsz;

	if (unlikely(!pskb_may_pull(skb, EHDR_MIN_SIZE)))
		return false;

	ehdr = (struct tipc_ehdr *)skb->data;
	if (unlikely(ehdr->version != TIPC_EVERSION))
		return false;
	ehsz = tipc_ehdr_size(ehdr);
	if (unlikely(!pskb_may_pull(skb, ehsz)))
		return false;
	if (unlikely(skb->len <= ehsz + TIPC_AES_GCM_TAG_SIZE))
		return false;

	return true;
}


static char *tipc_crypto_key_dump(struct tipc_crypto *c, char *buf)
{
	struct tipc_key key = c->key;
	struct tipc_aead *aead;
	int k, i = 0;
	char *s;

	for (k = KEY_MIN; k <= KEY_MAX; k++) {
		if (k == KEY_MASTER) {
			if (is_rx(c))
				continue;
			if (time_before(jiffies,
					c->timer2 + TIPC_TX_GRACE_PERIOD))
				s = "ACT";
			else
				s = "PAS";
		} else {
			if (k == key.passive)
				s = "PAS";
			else if (k == key.active)
				s = "ACT";
			else if (k == key.pending)
				s = "PEN";
			else
				s = "-";
		}
		i += scnprintf(buf + i, 200 - i, "\tKey%d: %s", k, s);

		rcu_read_lock();
		aead = rcu_dereference(c->aead[k]);
		if (aead)
			i += scnprintf(buf + i, 200 - i,
				       "{\"0x...%s\", \"%s\"}/%d:%d",
				       aead->hint,
				       (aead->mode == CLUSTER_KEY) ? "c" : "p",
				       atomic_read(&aead->users),
				       refcount_read(&aead->refcnt));
		rcu_read_unlock();
		i += scnprintf(buf + i, 200 - i, "\n");
	}

	if (is_rx(c))
		i += scnprintf(buf + i, 200 - i, "\tPeer RX active: %d\n",
			       atomic_read(&c->peer_rx_active));

	return buf;
}


int tipc_crypto_key_init(struct tipc_crypto *c, struct tipc_aead_key *ukey,
			 u8 mode, bool master_key)
{
	struct tipc_aead *aead = NULL;
	int rc = 0;

	/* Initiate with the new user key */
	rc = tipc_aead_init(&aead, ukey, mode);

	/* Attach it to the crypto */
	if (likely(!rc)) {
		rc = tipc_crypto_key_attach(c, aead, 0, master_key);
		if (rc < 0)
			tipc_aead_free(&aead->rcu);
	}

	return rc;
}


static int tipc_aead_init(struct tipc_aead **aead, struct tipc_aead_key *ukey,
			  u8 mode)
{
	struct tipc_tfm *tfm_entry, *head;
	struct crypto_aead *tfm;
	struct tipc_aead *tmp;
	int keylen, err, cpu;
	int tfm_cnt = 0;

	if (unlikely(*aead))
		return -EEXIST;

	/* Allocate a new AEAD */
	tmp = kzalloc(sizeof(*tmp), GFP_ATOMIC);
	if (unlikely(!tmp))
		return -ENOMEM;

	/* The key consists of two parts: [AES-KEY][SALT] */
	keylen = ukey->keylen - TIPC_AES_GCM_SALT_SIZE;

	/* Allocate per-cpu TFM entry pointer */
	tmp->tfm_entry = alloc_percpu(struct tipc_tfm *);
	if (!tmp->tfm_entry) {
		kfree_sensitive(tmp);
		return -ENOMEM;
	}

	/* Make a list of TFMs with the user key data */
	do {
		tfm = crypto_alloc_aead(ukey->alg_name, 0, 0);
		if (IS_ERR(tfm)) {
			err = PTR_ERR(tfm);
			break;
		}

		if (unlikely(!tfm_cnt &&
			     crypto_aead_ivsize(tfm) != TIPC_AES_GCM_IV_SIZE)) {
			crypto_free_aead(tfm);
			err = -ENOTSUPP;
			break;
		}

		err = crypto_aead_setauthsize(tfm, TIPC_AES_GCM_TAG_SIZE);
		err |= crypto_aead_setkey(tfm, ukey->key, keylen);
		if (unlikely(err)) {
			crypto_free_aead(tfm);
			break;
		}

		tfm_entry = kmalloc(sizeof(*tfm_entry), GFP_KERNEL);
		if (unlikely(!tfm_entry)) {
			crypto_free_aead(tfm);
			err = -ENOMEM;
			break;
		}
		INIT_LIST_HEAD(&tfm_entry->list);
		tfm_entry->tfm = tfm;

		/* First entry? */
		if (!tfm_cnt) {
			head = tfm_entry;
			for_each_possible_cpu(cpu) {
				*per_cpu_ptr(tmp->tfm_entry, cpu) = head;
			}
		} else {
			list_add_tail(&tfm_entry->list, &head->list);
		}

	} while (++tfm_cnt < sysctl_tipc_max_tfms);

	/* Not any TFM is allocated? */
	if (!tfm_cnt) {
		free_percpu(tmp->tfm_entry);
		kfree_sensitive(tmp);
		return err;
	}

	/* Form a hex string of some last bytes as the key's hint */
	bin2hex(tmp->hint, ukey->key + keylen - TIPC_AEAD_HINT_LEN,
		TIPC_AEAD_HINT_LEN);

	/* Initialize the other data */
	tmp->mode = mode;
	tmp->cloned = NULL;
	tmp->authsize = TIPC_AES_GCM_TAG_SIZE;
	tmp->key = kmemdup(ukey, tipc_aead_key_size(ukey), GFP_KERNEL);
	memcpy(&tmp->salt, ukey->key + keylen, TIPC_AES_GCM_SALT_SIZE);
	atomic_set(&tmp->users, 0);
	atomic64_set(&tmp->seqno, 0);
	refcount_set(&tmp->refcnt, 1);

	*aead = tmp;
	return 0;
}


static void *tipc_aead_mem_alloc(struct crypto_aead *tfm,
				 unsigned int crypto_ctx_size,
				 u8 **iv, struct aead_request **req,
				 struct scatterlist **sg, int nsg)
{
	unsigned int iv_size, req_size;
	unsigned int len;
	u8 *mem;

	iv_size = crypto_aead_ivsize(tfm);
	req_size = sizeof(**req) + crypto_aead_reqsize(tfm);

	len = crypto_ctx_size;
	len += iv_size;
	len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1);
	len = ALIGN(len, crypto_tfm_ctx_alignment());
	len += req_size;
	len = ALIGN(len, __alignof__(struct scatterlist));
	len += nsg * sizeof(**sg);

	mem = kmalloc(len, GFP_ATOMIC);
	if (!mem)
		return NULL;

	*iv = (u8 *)PTR_ALIGN(mem + crypto_ctx_size,
			      crypto_aead_alignmask(tfm) + 1);
	*req = (struct aead_request *)PTR_ALIGN(*iv + iv_size,
						crypto_tfm_ctx_alignment());
	*sg = (struct scatterlist *)PTR_ALIGN((u8 *)*req + req_size,
					      __alignof__(struct scatterlist));

	return (void *)mem;
}