db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: USB: digi_acceleport: do sanity checking for the number of ports

The driver can be crashed with devices that expose crafted descriptors
with too few endpoints.

See: http://seclists.org/bugtraq/2016/Mar/61

Signed-off-by: Oliver Neukum <ONeukum@suse.com>
[johan: fix OOB endpoint check and add error messages ]
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CVE: CVE-2016-3140
CWE: CWE-703
Vulnerability description: The digi_port_init function in drivers/usb/serial/digi_acceleport.c in the Linux kernel before 4.5.1 allows physically proximate attackers to cause a denial of service (NULL pointer dereference and system crash) via a crafted endpoints value in a USB device descriptor.

Project: linux
File: digi_acceleport.c

 static int digi_startup(struct usb_serial *serial)
 {
	struct device *dev = &serial->interface->dev;
 	struct digi_serial *serial_priv;
 	int ret;
	int i;

	/* check whether the device has the expected number of endpoints */
	if (serial->num_port_pointers < serial->type->num_ports + 1) {
		dev_err(dev, "OOB endpoints missing\n");
		return -ENODEV;
	}

	for (i = 0; i < serial->type->num_ports + 1 ; i++) {
		if (!serial->port[i]->read_urb) {
			dev_err(dev, "bulk-in endpoint missing\n");
			return -ENODEV;
		}
		if (!serial->port[i]->write_urb) {
			dev_err(dev, "bulk-out endpoint missing\n");
			return -ENODEV;
		}
	}
 
 	serial_priv = kzalloc(sizeof(*serial_priv), GFP_KERNEL);
 	if (!serial_priv)
		return -ENOMEM;

	spin_lock_init(&serial_priv->ds_serial_lock);
	serial_priv->ds_oob_port_num = serial->type->num_ports;
	serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];

	ret = digi_port_init(serial_priv->ds_oob_port,
						serial_priv->ds_oob_port_num);
	if (ret) {
		kfree(serial_priv);
		return ret;
	}

	usb_set_serial_data(serial, serial_priv);

	return 0;
}
Commit message: USB: mct_u232: add sanity checking in probe

An attack using the lack of sanity checking in probe is known. This
patch checks for the existence of a second port.

CVE-2016-3136

Signed-off-by: Oliver Neukum <ONeukum@suse.com>
CC: stable@vger.kernel.org
[johan: add error message ]
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
CVE: CVE-2016-3136
CWE: CWE-703
Vulnerability description: The mct_u232_msr_to_state function in drivers/usb/serial/mct_u232.c in the Linux kernel before 4.5.1 allows physically proximate attackers to cause a denial of service (NULL pointer dereference and system crash) via a crafted USB device without two interrupt-in endpoint descriptors.

Project: linux
File: mct_u232.c

 static int mct_u232_port_probe(struct usb_serial_port *port)
 {
	struct usb_serial *serial = port->serial;
 	struct mct_u232_private *priv;
 
	/* check first to simplify error handling */
	if (!serial->port[1] || !serial->port[1]->interrupt_in_urb) {
		dev_err(&port->dev, "expected endpoint missing\n");
		return -ENODEV;
	}

 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
 
 	/* Use second interrupt-in endpoint for reading. */
	priv->read_urb = serial->port[1]->interrupt_in_urb;
 	priv->read_urb->context = port;
 
 	spin_lock_init(&priv->lock);

	usb_set_serial_port_data(port, priv);

	return 0;
}
Commit message: netfilter: x_tables: check for size overflow

Ben Hawkes says:
 integer overflow in xt_alloc_table_info, which on 32-bit systems can
 lead to small structure allocation and a copy_from_user based heap
 corruption.

Reported-by: Ben Hawkes <hawkes@google.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
CVE: CVE-2016-3135
CWE: CWE-189
Vulnerability description: Integer overflow in the xt_alloc_table_info function in net/netfilter/x_tables.c in the Linux kernel through 4.5.2 on 32-bit platforms allows local users to gain privileges or cause a denial of service (heap memory corruption) via an IPT_SO_SET_REPLACE setsockopt call.

Project: linux
File: x_tables.c

struct xt_table_info *xt_alloc_table_info(unsigned int size)
{
 	struct xt_table_info *info = NULL;
 	size_t sz = sizeof(*info) + size;
 
	if (sz < sizeof(*info))
		return NULL;

 	/* Pedantry: prevent them from hitting BUG() in vmalloc.c --RR */
 	if ((SMP_ALIGN(size) >> PAGE_SHIFT) + 2 > totalram_pages)
 		return NULL;

	if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
		info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
	if (!info) {
		info = vmalloc(sz);
		if (!info)
			return NULL;
	}
	memset(info, 0, sizeof(*info));
	info->size = size;
	return info;
}
Commit message: Fix bug #71735: Double-free in SplDoublyLinkedList::offsetSet
CVE: CVE-2016-3132
CWE: CWE-415
Vulnerability description: Double free vulnerability in the SplDoublyLinkedList::offsetSet function in ext/spl/spl_dllist.c in PHP 7.x before 7.0.6 allows remote attackers to execute arbitrary code via a crafted index.

Project: php-src

SPL_METHOD(SplDoublyLinkedList, offsetSet)
{
	zval                  *zindex, *value;
	spl_dllist_object     *intern;

	if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &zindex, &value) == FAILURE) {
		return;
	}

	intern = Z_SPLDLLIST_P(getThis());

	if (Z_TYPE_P(zindex) == IS_NULL) {
		/* $obj[] = ... */
		spl_ptr_llist_push(intern->llist, value);
	} else {
		/* $obj[$foo] = ... */
		zend_long                   index;
		spl_ptr_llist_element *element;

 		index = spl_offset_convert_to_long(zindex);
 
 		if (index < 0 || index >= intern->llist->count) {
 			zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid or out of range", 0);
 			return;
 		}

		element = spl_ptr_llist_offset(intern->llist, index, intern->flags & SPL_DLLIST_IT_LIFO);

		if (element != NULL) {
			/* call dtor on the old element as in spl_ptr_llist_pop */
			if (intern->llist->dtor) {
				intern->llist->dtor(element);
			}

			/* the element is replaced, delref the old one as in
			 * SplDoublyLinkedList::pop() */
			zval_ptr_dtor(&element->data);
			ZVAL_COPY_VALUE(&element->data, value);

			/* new element, call ctor as in spl_ptr_llist_push */
			if (intern->llist->ctor) {
				intern->llist->ctor(element);
			}
		} else {
			zval_ptr_dtor(value);
			zend_throw_exception(spl_ce_OutOfRangeException, "Offset invalid", 0);
			return;
		}
	}
} /* }}} */

/* {{{ proto void SplDoublyLinkedList::offsetUnset(mixed index)
Commit message: gd2: handle corrupt images better (CVE-2016-3074)

Make sure we do some range checking on corrupted chunks.

Thanks to Hans Jerry Illikainen <hji@dyntopia.com> for indepth report
and reproducer information.  Made for easy test case writing :).
CVE: CVE-2016-3074
CWE: CWE-189
Vulnerability description: Integer signedness error in GD Graphics Library 2.1.1 (aka libgd or libgd2) allows remote attackers to cause a denial of service (crash) or potentially execute arbitrary code via crafted compressed gd2 data, which triggers a heap-based buffer overflow.

Project: libgd

_gd2GetHeader (gdIOCtxPtr in, int *sx, int *sy,
               int *cs, int *vers, int *fmt, int *ncx, int *ncy,
               t_chunk_info ** chunkIdx)
{
	int i;
	int ch;
	char id[5];
	t_chunk_info *cidx;
	int sidx;
	int nc;

	GD2_DBG (printf ("Reading gd2 header info\n"));

	for (i = 0; i < 4; i++) {
		ch = gdGetC (in);
		if (ch == EOF) {
			goto fail1;
		};
		id[i] = ch;
	};
	id[4] = 0;

	GD2_DBG (printf ("Got file code: %s\n", id));

	/* Equiv. of 'magick'.  */
	if (strcmp (id, GD2_ID) != 0) {
		GD2_DBG (printf ("Not a valid gd2 file\n"));
		goto fail1;
	};

	/* Version */
	if (gdGetWord (vers, in) != 1) {
		goto fail1;
	};
	GD2_DBG (printf ("Version: %d\n", *vers));

	if ((*vers != 1) && (*vers != 2)) {
		GD2_DBG (printf ("Bad version: %d\n", *vers));
		goto fail1;
	};

	/* Image Size */
	if (!gdGetWord (sx, in)) {
		GD2_DBG (printf ("Could not get x-size\n"));
		goto fail1;
	}
	if (!gdGetWord (sy, in)) {
		GD2_DBG (printf ("Could not get y-size\n"));
		goto fail1;
	}
	GD2_DBG (printf ("Image is %dx%d\n", *sx, *sy));

	/* Chunk Size (pixels, not bytes!) */
	if (gdGetWord (cs, in) != 1) {
		goto fail1;
	};
	GD2_DBG (printf ("ChunkSize: %d\n", *cs));

	if ((*cs < GD2_CHUNKSIZE_MIN) || (*cs > GD2_CHUNKSIZE_MAX)) {
		GD2_DBG (printf ("Bad chunk size: %d\n", *cs));
		goto fail1;
	};

	/* Data Format */
	if (gdGetWord (fmt, in) != 1) {
		goto fail1;
	};
	GD2_DBG (printf ("Format: %d\n", *fmt));

	if ((*fmt != GD2_FMT_RAW) && (*fmt != GD2_FMT_COMPRESSED) &&
	        (*fmt != GD2_FMT_TRUECOLOR_RAW) &&
	        (*fmt != GD2_FMT_TRUECOLOR_COMPRESSED)) {
		GD2_DBG (printf ("Bad data format: %d\n", *fmt));
		goto fail1;
	};


	/* # of chunks wide */
	if (gdGetWord (ncx, in) != 1) {
		goto fail1;
	};
	GD2_DBG (printf ("%d Chunks Wide\n", *ncx));

	/* # of chunks high */
	if (gdGetWord (ncy, in) != 1) {
		goto fail1;
	};
	GD2_DBG (printf ("%d Chunks vertically\n", *ncy));

	if (gd2_compressed (*fmt)) {
		nc = (*ncx) * (*ncy);
		GD2_DBG (printf ("Reading %d chunk index entries\n", nc));
		sidx = sizeof (t_chunk_info) * nc;
		cidx = gdCalloc (sidx, 1);
		if (!cidx) {
			goto fail1;
		}
		for (i = 0; i < nc; i++) {
			if (gdGetInt (&cidx[i].offset, in) != 1) {
				goto fail2;
			};
 			if (gdGetInt (&cidx[i].size, in) != 1) {
 				goto fail2;
 			};
			if (cidx[i].offset < 0 || cidx[i].size < 0)
				goto fail2;
 		};
 		*chunkIdx = cidx;
 	};

	GD2_DBG (printf ("gd2 header complete\n"));

	return 1;
fail2:
	gdFree(cidx);
fail1:
	return 0;
}
Commit message: USB: visor: fix null-deref at probe

Fix null-pointer dereference at probe should a (malicious) Treo device
lack the expected endpoints.

Specifically, the Treo port-setup hack was dereferencing the bulk-in and
interrupt-in urbs without first making sure they had been allocated by
core.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
CVE: CVE-2016-2782
CWE: CWE-703
Vulnerability description: The treo_attach function in drivers/usb/serial/visor.c in the Linux kernel before 4.5 allows physically proximate attackers to cause a denial of service (NULL pointer dereference and system crash) or possibly have unspecified other impact by inserting a USB device that lacks a (1) bulk-in or (2) interrupt-in endpoint.

Project: linux
File: visor.c

static int treo_attach(struct usb_serial *serial)
{
	struct usb_serial_port *swap_port;

	/* Only do this endpoint hack for the Handspring devices with
	 * interrupt in endpoints, which for now are the Treo devices. */
	if (!((le16_to_cpu(serial->dev->descriptor.idVendor)
						== HANDSPRING_VENDOR_ID) ||
		(le16_to_cpu(serial->dev->descriptor.idVendor)
						== KYOCERA_VENDOR_ID)) ||
 		(serial->num_interrupt_in == 0))
 		return 0;
 
	if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
		dev_err(&serial->interface->dev, "missing endpoints\n");
		return -ENODEV;
	}

 	/*
 	* It appears that Treos and Kyoceras want to use the
 	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
	* so let's swap the 1st and 2nd bulk in and interrupt endpoints.
	* Note that swapping the bulk out endpoints would break lots of
	* apps that want to communicate on the second port.
	*/
#define COPY_PORT(dest, src)						\
	do { \
		int i;							\
									\
		for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) {	\
			dest->read_urbs[i] = src->read_urbs[i];		\
			dest->read_urbs[i]->context = dest;		\
			dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; \
		}							\
		dest->read_urb = src->read_urb;				\
		dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\
		dest->bulk_in_buffer = src->bulk_in_buffer;		\
		dest->bulk_in_size = src->bulk_in_size;			\
		dest->interrupt_in_urb = src->interrupt_in_urb;		\
		dest->interrupt_in_urb->context = dest;			\
		dest->interrupt_in_endpointAddress = \
					src->interrupt_in_endpointAddress;\
		dest->interrupt_in_buffer = src->interrupt_in_buffer;	\
	} while (0);

	swap_port = kmalloc(sizeof(*swap_port), GFP_KERNEL);
	if (!swap_port)
		return -ENOMEM;
	COPY_PORT(swap_port, serial->port[0]);
	COPY_PORT(serial->port[0], serial->port[1]);
	COPY_PORT(serial->port[1], swap_port);
	kfree(swap_port);

	return 0;
}
Commit message: ALSA: seq: Fix race at timer setup and close

ALSA sequencer code has an open race between the timer setup ioctl and
the close of the client.  This was triggered by syzkaller fuzzer, and
a use-after-free was caught there as a result.

This patch papers over it by adding a proper queue->timer_mutex lock
around the timer-related calls in the relevant code path.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
CVE: CVE-2016-2544
CWE: CWE-362
Vulnerability description: Race condition in the queue_delete function in sound/core/seq/seq_queue.c in the Linux kernel before 4.4.1 allows local users to cause a denial of service (use-after-free and system crash) by making an ioctl call at a certain time.

Project: linux
File: seq_queue.c

 static void queue_delete(struct snd_seq_queue *q)
 {
 	/* stop and release the timer */
	mutex_lock(&q->timer_mutex);
 	snd_seq_timer_stop(q->timer);
 	snd_seq_timer_close(q);
	mutex_unlock(&q->timer_mutex);
 	/* wait until access free */
 	snd_use_lock_sync(&q->use_lock);
 	/* release resources... */
	snd_seq_prioq_delete(&q->tickq);
	snd_seq_prioq_delete(&q->timeq);
	snd_seq_timer_delete(&q->timer);

	kfree(q);
}
Commit message: ALSA: seq: Fix missing NULL check at remove_events ioctl

snd_seq_ioctl_remove_events() calls snd_seq_fifo_clear()
unconditionally even if there is no FIFO assigned, and this leads to
an Oops due to NULL dereference.  The fix is just to add a proper NULL
check.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
CVE: CVE-2016-2543
CWE: CWE-703
Vulnerability description: The snd_seq_ioctl_remove_events function in sound/core/seq/seq_clientmgr.c in the Linux kernel before 4.4.1 does not verify FIFO assignment before proceeding with FIFO clearing, which allows local users to cause a denial of service (NULL pointer dereference and OOPS) via a crafted ioctl call.

Project: linux

static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
				       void __user *arg)
{
	struct snd_seq_remove_events info;

	if (copy_from_user(&info, arg, sizeof(info)))
		return -EFAULT;

	/*
	 * Input mostly not implemented XXX.
	 */
	if (info.remove_mode & SNDRV_SEQ_REMOVE_INPUT) {
		/*
 		 * No restrictions so for a user client we can clear
 		 * the whole fifo
 		 */
		if (client->type == USER_CLIENT && client->data.user.fifo)
 			snd_seq_fifo_clear(client->data.user.fifo);
 	}
 
	if (info.remove_mode & SNDRV_SEQ_REMOVE_OUTPUT)
		snd_seq_queue_remove_cells(client->number, &info);

	return 0;
}
Commit message: prefer memcpy to strcpy

When we already know the length of a string (e.g., because
we just malloc'd to fit it), it's nicer to use memcpy than
strcpy, as it makes it more obvious that we are not going to
overflow the buffer (because the size we pass matches the
size in the allocation).

This also eliminates calls to strcpy, which make auditing
the code base harder.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
CVE: CVE-2016-2315
CWE: CWE-119
Vulnerability description: revision.c in git before 2.7.4 uses an incorrect integer data type, which allows remote attackers to execute arbitrary code via a (1) long filename or (2) many nested trees, leading to a heap-based buffer overflow.

Project: git
File: fast-import.c

 static char *pool_strdup(const char *s)
 {
	size_t len = strlen(s) + 1;
	char *r = pool_alloc(len);
	memcpy(r, s, len);
 	return r;
 }

Project: git
File: revision.c

char *path_name(const struct name_path *path, const char *name)
{
	const struct name_path *p;
	char *n, *m;
	int nlen = strlen(name);
	int len = nlen + 1;

	for (p = path; p; p = p->up) {
		if (p->elem_len)
			len += p->elem_len + 1;
 	}
 	n = xmalloc(len);
 	m = n + len - (nlen + 1);
	memcpy(m, name, nlen + 1);
 	for (p = path; p; p = p->up) {
 		if (p->elem_len) {
 			m -= p->elem_len + 1;
			memcpy(m, p->elem, p->elem_len);
			m[p->elem_len] = '/';
		}
	}
	return n;
}
Commit message: ALSA: usb-audio: Fix NULL dereference in create_fixed_stream_quirk()

create_fixed_stream_quirk() may cause a NULL-pointer dereference by
accessing the non-existing endpoint when a USB device with a malformed
USB descriptor is used.

This patch avoids it simply by adding a sanity check of bNumEndpoints
before the accesses.

Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=971125
Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
CVE: CVE-2016-2184
Vulnerability description: The create_fixed_stream_quirk function in sound/usb/quirks.c in the snd-usb-audio driver in the Linux kernel before 4.5.1 allows physically proximate attackers to cause a denial of service (NULL pointer dereference or double free, and system crash) via a crafted endpoints value in a USB device descriptor.

Project: linux
File: quirks.c

static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
				     struct usb_interface *iface,
				     struct usb_driver *driver,
				     const struct snd_usb_audio_quirk *quirk)
{
	struct audioformat *fp;
	struct usb_host_interface *alts;
	struct usb_interface_descriptor *altsd;
	int stream, err;
	unsigned *rate_table = NULL;

	fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
	if (!fp) {
		usb_audio_err(chip, "cannot memdup\n");
		return -ENOMEM;
	}
	if (fp->nr_rates > MAX_NR_RATES) {
		kfree(fp);
		return -EINVAL;
	}
	if (fp->nr_rates > 0) {
		rate_table = kmemdup(fp->rate_table,
				     sizeof(int) * fp->nr_rates, GFP_KERNEL);
		if (!rate_table) {
			kfree(fp);
			return -ENOMEM;
		}
		fp->rate_table = rate_table;
	}

	stream = (fp->endpoint & USB_DIR_IN)
		? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
	err = snd_usb_add_audio_stream(chip, stream, fp);
	if (err < 0) {
		kfree(fp);
		kfree(rate_table);
		return err;
	}
	if (fp->iface != get_iface_desc(&iface->altsetting[0])->bInterfaceNumber ||
	    fp->altset_idx >= iface->num_altsetting) {
		kfree(fp);
		kfree(rate_table);
		return -EINVAL;
 	}
 	alts = &iface->altsetting[fp->altset_idx];
 	altsd = get_iface_desc(alts);
	if (altsd->bNumEndpoints < 1) {
		kfree(fp);
		kfree(rate_table);
		return -EINVAL;
	}

 	fp->protocol = altsd->bInterfaceProtocol;
 
 	if (fp->datainterval == 0)
		fp->datainterval = snd_usb_parse_datainterval(chip, alts);
	if (fp->maxpacksize == 0)
		fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
	usb_set_interface(chip->dev, fp->iface, 0);
	snd_usb_init_pitch(chip, fp->iface, alts, fp);
	snd_usb_init_sample_rate(chip, fp->iface, alts, fp, fp->rate_max);
	return 0;
}
Commit message: EVM: Use crypto_memneq() for digest comparisons

This patch fixes vulnerability CVE-2016-2085.  The problem exists
because the vm_verify_hmac() function includes a use of memcmp().
Unfortunately, this allows timing side channel attacks; specifically
a MAC forgery complexity drop from 2^128 to 2^12.  This patch changes
the memcmp() to the cryptographically safe crypto_memneq().

Reported-by: Xiaofei Rex Guo <xiaofei.rex.guo@intel.com>
Signed-off-by: Ryan Ware <ware@linux.intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Signed-off-by: James Morris <james.l.morris@oracle.com>
CVE: CVE-2016-2085
CWE: CWE-19
Vulnerability description: The evm_verify_hmac function in security/integrity/evm/evm_main.c in the Linux kernel before 4.5 does not properly copy data, which makes it easier for local users to forge MAC values via a timing side-channel attack.

Project: linux
File: evm_main.c

static enum integrity_status evm_verify_hmac(struct dentry *dentry,
					     const char *xattr_name,
					     char *xattr_value,
					     size_t xattr_value_len,
					     struct integrity_iint_cache *iint)
{
	struct evm_ima_xattr_data *xattr_data = NULL;
	struct evm_ima_xattr_data calc;
	enum integrity_status evm_status = INTEGRITY_PASS;
	int rc, xattr_len;

	if (iint && iint->evm_status == INTEGRITY_PASS)
		return iint->evm_status;

	/* if status is not PASS, try to check again - against -ENOMEM */

	/* first need to know the sig type */
	rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0,
				GFP_NOFS);
	if (rc <= 0) {
		evm_status = INTEGRITY_FAIL;
		if (rc == -ENODATA) {
			rc = evm_find_protected_xattrs(dentry);
			if (rc > 0)
				evm_status = INTEGRITY_NOLABEL;
			else if (rc == 0)
				evm_status = INTEGRITY_NOXATTRS; /* new file */
		} else if (rc == -EOPNOTSUPP) {
			evm_status = INTEGRITY_UNKNOWN;
		}
		goto out;
	}

	xattr_len = rc;

	/* check value type */
	switch (xattr_data->type) {
	case EVM_XATTR_HMAC:
		rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
 				   xattr_value_len, calc.digest);
 		if (rc)
 			break;
		rc = crypto_memneq(xattr_data->digest, calc.digest,
 			    sizeof(calc.digest));
 		if (rc)
 			rc = -EINVAL;
		break;
	case EVM_IMA_XATTR_DIGSIG:
		rc = evm_calc_hash(dentry, xattr_name, xattr_value,
				xattr_value_len, calc.digest);
		if (rc)
			break;
		rc = integrity_digsig_verify(INTEGRITY_KEYRING_EVM,
					(const char *)xattr_data, xattr_len,
					calc.digest, sizeof(calc.digest));
		if (!rc) {
			/* Replace RSA with HMAC if not mounted readonly and
			 * not immutable
			 */
			if (!IS_RDONLY(d_backing_inode(dentry)) &&
			    !IS_IMMUTABLE(d_backing_inode(dentry)))
				evm_update_evmxattr(dentry, xattr_name,
						    xattr_value,
						    xattr_value_len);
		}
		break;
	default:
		rc = -EINVAL;
		break;
	}

	if (rc)
		evm_status = (rc == -ENODATA) ?
				INTEGRITY_NOXATTRS : INTEGRITY_FAIL;
out:
	if (iint)
		iint->evm_status = evm_status;
	kfree(xattr_data);
	return evm_status;
}