db-d2/primevul-codebert-embeddings huggingface dataset:
Commit message: Fixed a GIF decoding bug (divide by zero)

Fixes issue #15
CVE: CVE-2017-7962
CWE: CWE-369
Vulnerability description: The iwgif_read_image function in imagew-gif.c in libimageworsener.a in ImageWorsener 1.3.0 allows remote attackers to cause a denial of service (divide-by-zero error and application crash) via a crafted file.

Project: imageworsener

static int iwgif_read_image(struct iwgifrcontext *rctx)
{
	int retval=0;
	struct lzwdeccontext d;
	size_t subblocksize;
	int has_local_ct;
	int local_ct_size;

	unsigned int root_codesize;

	if(!iwgif_read(rctx,rctx->rbuf,9)) goto done;

	rctx->image_left = (int)iw_get_ui16le(&rctx->rbuf[0]);
	rctx->image_top = (int)iw_get_ui16le(&rctx->rbuf[2]);
 
 	rctx->image_width = (int)iw_get_ui16le(&rctx->rbuf[4]);
 	rctx->image_height = (int)iw_get_ui16le(&rctx->rbuf[6]);
	if(rctx->image_width<1 || rctx->image_height<1) {
		iw_set_error(rctx->ctx, "Invalid image dimensions");
		goto done;
	}
 
 	rctx->interlaced = (int)((rctx->rbuf[8]>>6)&0x01);
 
	has_local_ct = (int)((rctx->rbuf[8]>>7)&0x01);
	if(has_local_ct) {
		local_ct_size = (int)(rctx->rbuf[8]&0x07);
		rctx->colortable.num_entries = 1<<(1+local_ct_size);
	}

	if(has_local_ct) {
		if(!iwgif_read_color_table(rctx,&rctx->colortable)) goto done;
	}

	if(rctx->has_transparency) {
	    rctx->colortable.entry[rctx->trans_color_index].a = 0;
	}

	if(!iwgif_read(rctx,rctx->rbuf,1)) goto done;
	root_codesize = (unsigned int)rctx->rbuf[0];

	if(root_codesize<2 || root_codesize>11) {
		iw_set_error(rctx->ctx,"Invalid LZW minimum code size");
		goto done;
	}

	if(!iwgif_init_screen(rctx)) goto done;

	rctx->total_npixels = (size_t)rctx->image_width * (size_t)rctx->image_height;

	if(!iwgif_make_row_pointers(rctx)) goto done;

	lzw_init(&d,root_codesize);
	lzw_clear(&d);

	while(1) {
		if(!iwgif_read(rctx,rctx->rbuf,1)) goto done;
		subblocksize = (size_t)rctx->rbuf[0];
		if(subblocksize==0) break;

		if(!iwgif_read(rctx,rctx->rbuf,subblocksize)) goto done;
		if(!lzw_process_bytes(rctx,&d,rctx->rbuf,subblocksize)) goto done;

		if(d.eoi_flag) break;

		if(rctx->pixels_set >= rctx->total_npixels) break;
	}

	retval=1;

done:
	return retval;
}
Commit message: Fix double-free/OOB-write while receiving IPC data

If a malicious client pretends to be the E17 window manager, it is
possible to trigger an out of boundary heap write while receiving an
IPC message.

The length of the already received message is stored in an unsigned
short, which overflows after receiving 64 KB of data. It's comparably
small amount of data and therefore achievable for an attacker.

When len overflows, realloc() will either be called with a small value
and therefore chars will be appended out of bounds, or len + 1 will be
exactly 0, in which case realloc() behaves like free(). This could be
abused for a later double-free attack as it's even possible to overwrite
the free information -- but this depends on the malloc implementation.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
CVE: CVE-2017-7875
CWE: CWE-787
Vulnerability description: In wallpaper.c in feh before v2.18.3, if a malicious client pretends to be the E17 window manager, it is possible to trigger an out-of-boundary heap write while receiving an IPC message. An integer overflow leads to a buffer overflow and/or a double free.

Project: feh

char *enl_ipc_get(const char *msg_data)
 {
 
 	static char *message = NULL;
	static size_t len = 0;
 	char buff[13], *ret_msg = NULL;
 	register unsigned char i;
 	unsigned char blen;

	if (msg_data == IPC_TIMEOUT) {
		return(IPC_TIMEOUT);
	}
	for (i = 0; i < 12; i++) {
		buff[i] = msg_data[i];
	}
	buff[12] = 0;
	blen = strlen(buff);
	if (message != NULL) {
		len += blen;
		message = (char *) erealloc(message, len + 1);
		strcat(message, buff);
	} else {
		len = blen;
		message = (char *) emalloc(len + 1);
		strcpy(message, buff);
	}
	if (blen < 12) {
		ret_msg = message;
		message = NULL;
		D(("Received complete reply:  \"%s\"\n", ret_msg));
	}
	return(ret_msg);
}
Commit message: avcodec/pngdec: Fix off by 1 size in decode_zbuf()

Fixes out of array access
Fixes: 444/fuzz-2-ffmpeg_VIDEO_AV_CODEC_ID_PNG_fuzzer

Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/targets/ffmpeg
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
CVE: CVE-2017-7866
CWE: CWE-787
Vulnerability description: FFmpeg before 2017-01-23 has an out-of-bounds write caused by a stack-based buffer overflow related to the decode_zbuf function in libavcodec/pngdec.c.

Project: FFmpeg
File: pngdec.c

static int decode_zbuf(AVBPrint *bp, const uint8_t *data,
                       const uint8_t *data_end)
{
    z_stream zstream;
    unsigned char *buf;
    unsigned buf_size;
    int ret;

    zstream.zalloc = ff_png_zalloc;
    zstream.zfree  = ff_png_zfree;
    zstream.opaque = NULL;
    if (inflateInit(&zstream) != Z_OK)
        return AVERROR_EXTERNAL;
    zstream.next_in  = (unsigned char *)data;
    zstream.avail_in = data_end - data;
     av_bprint_init(bp, 0, -1);
 
     while (zstream.avail_in > 0) {
        av_bprint_get_buffer(bp, 2, &buf, &buf_size);
        if (buf_size < 2) {
             ret = AVERROR(ENOMEM);
             goto fail;
         }
         zstream.next_out  = buf;
        zstream.avail_out = buf_size - 1;
         ret = inflate(&zstream, Z_PARTIAL_FLUSH);
         if (ret != Z_OK && ret != Z_STREAM_END) {
             ret = AVERROR_EXTERNAL;
            goto fail;
        }
        bp->len += zstream.next_out - buf;
        if (ret == Z_STREAM_END)
            break;
    }
    inflateEnd(&zstream);
    bp->str[bp->len] = 0;
    return 0;

fail:
    inflateEnd(&zstream);
    av_bprint_finalize(bp, NULL);
    return ret;
}
Commit message: Fix crash in fuzzed wasm r2_hoobr_consume_init_expr
CVE: CVE-2017-7854
CWE: CWE-125
Vulnerability description: The consume_init_expr function in wasm.c in radare2 1.3.0 allows remote attackers to cause a denial of service (heap-based buffer over-read and application crash) via a crafted Web Assembly file.

Project: radare2

 static size_t consume_init_expr (ut8 *buf, ut8 *max, ut8 eoc, void *out, ut32 *offset) {
 	ut32 i = 0;
 	while (buf + i < max && buf[i] != eoc) {
		i++;
 	}
 	if (buf[i] != eoc) {
 		return 0;
	}
	if (offset) {
		*offset += i + 1;
	}
	return i + 1;
}

Project: radare2

 static RList *r_bin_wasm_get_element_entries (RBinWasmObj *bin, RBinWasmSection *sec) {
 	RList *ret = NULL;
 	RBinWasmElementEntry *ptr = NULL;
 
	if (!(ret = r_list_newf ((RListFree)free))) {
		return NULL;
 	}
 
 	ut8* buf = bin->buf->buf + (ut32)sec->payload_data;
	int buflen = bin->buf->length - (ut32)sec->payload_data;
 	ut32 len =  sec->payload_len;
 	ut32 count = sec->count;
 	ut32 i = 0, r = 0;
 
	while (i < len && len < buflen && r < count) {
 		if (!(ptr = R_NEW0 (RBinWasmElementEntry))) {
 			return ret;
 		}
 		if (!(consume_u32 (buf + i, buf + len, &ptr->index, &i))) {
			goto beach;
 		}
 		if (!(consume_init_expr (buf + i, buf + len, R_BIN_WASM_END_OF_CODE, NULL, &i))) {
			goto beach;
 		}
 		if (!(consume_u32 (buf + i, buf + len, &ptr->num_elem, &i))) {
			goto beach;
 		}
 		ut32 j = 0;
		while (i < len && j < ptr->num_elem) {
 			ut32 e;
 			if (!(consume_u32 (buf + i, buf + len, &e, &i))) {
 				free (ptr);
 				return ret;
 			}
 		}
 		r_list_append (ret, ptr);
 
 		r += 1;
 	}
	return ret;
beach:
	free (ptr);
 	return ret;
 }

Project: radare2
File: wasm.c

 static RList *r_bin_wasm_get_global_entries (RBinWasmObj *bin, RBinWasmSection *sec) {
 	RList *ret = NULL;
 	RBinWasmGlobalEntry *ptr = NULL;
 
 	if (!(ret = r_list_newf ((RListFree)free))) {
 		return NULL;
 	}
 
 	ut8* buf = bin->buf->buf + (ut32)sec->payload_data;
	int buflen = bin->buf->length - (ut32)sec->payload_data;
 	ut32 len =  sec->payload_len;
 	ut32 count = sec->count;
 	ut32 i = 0, r = 0;

	while (i < len && len < buflen && r < count) {
		if (!(ptr = R_NEW0 (RBinWasmGlobalEntry))) {
			return ret;
		}

		if (len + 8 > buflen || !(consume_u8 (buf + i, buf + len, (ut8*)&ptr->content_type, &i))) {
			goto beach;
		}
		if (len + 8 > buflen || !(consume_u8 (buf + i, buf + len, &ptr->mutability, &i))) {
			goto beach;
		}
		if (len + 8 > buflen || !(consume_init_expr (buf + i, buf + len, R_BIN_WASM_END_OF_CODE, NULL, &i))) {
			goto beach;
		}
		r_list_append (ret, ptr);
		r++;
	}
	return ret;
beach:
	free (ptr);
	return ret;
 }
Commit message: src/id3.c : Improve error handling
CVE: CVE-2017-7586
CWE: CWE-119
Vulnerability description: In libsndfile before 1.0.28, an error in the "header_read()" function (common.c) when handling ID3 tags can be exploited to cause a stack-based buffer overflow via a specially crafted FLAC file.

Project: libsndfile
File: id3.c

id3_skip (SF_PRIVATE * psf)
{	unsigned char	buf [10] ;

	memset (buf, 0, sizeof (buf)) ;
	psf_binheader_readf (psf, "pb", 0, buf, 10) ;

	if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3')
	{	int	offset = buf [6] & 0x7f ;
		offset = (offset << 7) | (buf [7] & 0x7f) ;
		offset = (offset << 7) | (buf [8] & 0x7f) ;
		offset = (offset << 7) | (buf [9] & 0x7f) ;

		psf_log_printf (psf, "ID3 length : %d\n--------------------\n", offset) ;

		/* Never want to jump backwards in a file. */
		if (offset < 0)
			return 0 ;
 
 		/* Calculate new file offset and position ourselves there. */
 		psf->fileoffset += offset + 10 ;
 
		if (psf->fileoffset < psf->filelength)
		{	psf_binheader_readf (psf, "p", psf->fileoffset) ;
			return 1 ;
			} ;
 		} ;
 
 	return 0 ;
} /* id3_skip */
Commit message: ipx: call ipxitf_put() in ioctl error path

We should call ipxitf_put() if the copy_to_user() fails.

Reported-by: 李强 <liqiang6-s@360.cn>
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2017-7487
CWE: CWE-416
Vulnerability description: The ipxitf_ioctl function in net/ipx/af_ipx.c in the Linux kernel through 4.11.1 mishandles reference counts, which allows local users to cause a denial of service (use-after-free) or possibly have unspecified other impact via a failed SIOCGIFADDR ioctl call for an IPX interface.

Project: linux

static int ipxitf_ioctl(unsigned int cmd, void __user *arg)
{
	int rc = -EINVAL;
	struct ifreq ifr;
	int val;

	switch (cmd) {
	case SIOCSIFADDR: {
		struct sockaddr_ipx *sipx;
		struct ipx_interface_definition f;

		rc = -EFAULT;
		if (copy_from_user(&ifr, arg, sizeof(ifr)))
			break;
		sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
		rc = -EINVAL;
		if (sipx->sipx_family != AF_IPX)
			break;
		f.ipx_network = sipx->sipx_network;
		memcpy(f.ipx_device, ifr.ifr_name,
			sizeof(f.ipx_device));
		memcpy(f.ipx_node, sipx->sipx_node, IPX_NODE_LEN);
		f.ipx_dlink_type = sipx->sipx_type;
		f.ipx_special = sipx->sipx_special;

		if (sipx->sipx_action == IPX_DLTITF)
			rc = ipxitf_delete(&f);
		else
			rc = ipxitf_create(&f);
		break;
	}
	case SIOCGIFADDR: {
		struct sockaddr_ipx *sipx;
		struct ipx_interface *ipxif;
		struct net_device *dev;

		rc = -EFAULT;
		if (copy_from_user(&ifr, arg, sizeof(ifr)))
			break;
		sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
		dev  = __dev_get_by_name(&init_net, ifr.ifr_name);
		rc   = -ENODEV;
		if (!dev)
			break;
		ipxif = ipxitf_find_using_phys(dev,
					   ipx_map_frame_type(sipx->sipx_type));
		rc = -EADDRNOTAVAIL;
		if (!ipxif)
			break;

		sipx->sipx_family	= AF_IPX;
 		sipx->sipx_network	= ipxif->if_netnum;
 		memcpy(sipx->sipx_node, ipxif->if_node,
 			sizeof(sipx->sipx_node));
		rc = 0;
 		if (copy_to_user(arg, &ifr, sizeof(ifr)))
			rc = -EFAULT;
 		ipxitf_put(ipxif);
 		break;
 	}
 	case SIOCAIPXITFCRT:
		rc = -EFAULT;
		if (get_user(val, (unsigned char __user *) arg))
			break;
		rc = 0;
		ipxcfg_auto_create_interfaces = val;
		break;
	case SIOCAIPXPRISLT:
		rc = -EFAULT;
		if (get_user(val, (unsigned char __user *) arg))
			break;
		rc = 0;
		ipxcfg_set_auto_select(val);
		break;
	}

	return rc;
}
Commit message: tcp: fix SCM_TIMESTAMPING_OPT_STATS for normal skbs

__sock_recv_timestamp can be called for both normal skbs (for
receive timestamps) and for skbs on the error queue (for transmit
timestamps).

Commit 1c885808e456
(tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING)
assumes any skb passed to __sock_recv_timestamp are from
the error queue, containing OPT_STATS in the content of the skb.
This results in accessing invalid memory or generating junk
data.

To fix this, set skb->pkt_type to PACKET_OUTGOING for packets
on the error queue. This is safe because on the receive path
on local sockets skb->pkt_type is never set to PACKET_OUTGOING.
With that, copy OPT_STATS from a packet, only if its pkt_type
is PACKET_OUTGOING.

Fixes: 1c885808e456 ("tcp: SOF_TIMESTAMPING_OPT_STATS option for SO_TIMESTAMPING")
Reported-by: JongHwan Kim <zzoru007@gmail.com>
Signed-off-by: Soheil Hassas Yeganeh <soheil@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
CVE: CVE-2017-7277
CWE: CWE-125
Vulnerability description: The TCP stack in the Linux kernel through 4.10.6 mishandles the SCM_TIMESTAMPING_OPT_STATS feature, which allows local users to obtain sensitive information from the kernel's internal socket data structures or cause a denial of service (out-of-bounds read) via crafted system calls, related to net/core/skbuff.c and net/socket.c.

Project: linux

int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
{
	if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
	    (unsigned int)sk->sk_rcvbuf)
		return -ENOMEM;

	skb_orphan(skb);
 	skb->sk = sk;
 	skb->destructor = sock_rmem_free;
 	atomic_add(skb->truesize, &sk->sk_rmem_alloc);
	skb_set_err_queue(skb);
 
 	/* before exiting rcu section, make sure dst is refcounted */
 	skb_dst_force(skb);

	skb_queue_tail(&sk->sk_error_queue, skb);
	if (!sock_flag(sk, SOCK_DEAD))
		sk->sk_data_ready(sk);
	return 0;
}
Commit message: Fix #7152 - Null deref in cms
CVE: CVE-2017-7274
CWE: CWE-476
Vulnerability description: The r_pkcs7_parse_cms function in libr/util/r_pkcs7.c in radare2 1.3.0 allows remote attackers to cause a denial of service (NULL pointer dereference and application crash) via a crafted PE file.

Project: radare2
File: r_pkcs7.c

RCMS *r_pkcs7_parse_cms (const ut8 *buffer, ut32 length) {
	RASN1Object *object;
	RCMS *container;
	if (!buffer || !length) {
		return NULL;
	}
	container = R_NEW0 (RCMS);
	if (!container) {
 		return NULL;
 	}
 	object = r_asn1_create_object (buffer, length);
	if (!object || object->list.length != 2 || !object->list.objects ||
		!object->list.objects[0] || !object->list.objects[1] ||
		object->list.objects[1]->list.length != 1) {
 		r_asn1_free_object (object);
 		free (container);
 		return NULL;
	}
	container->contentType = r_asn1_stringify_oid (object->list.objects[0]->sector, object->list.objects[0]->length);
	r_pkcs7_parse_signeddata (&container->signedData, object->list.objects[1]->list.objects[0]);
	r_asn1_free_object (object);
	return container;
}
Commit message: HID: hid-cypress: validate length of report

Make sure we have enough of a report structure to validate before
looking at it.

Reported-by: Benoit Camredon <benoit.camredon@airbus.com>
Tested-by: Benoit Camredon <benoit.camredon@airbus.com>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
CVE: CVE-2017-7273
CWE: CWE-703
Vulnerability description: The cp_report_fixup function in drivers/hid/hid-cypress.c in the Linux kernel 3.2 and 4.x before 4.9.4 allows physically proximate attackers to cause a denial of service (integer underflow) or possibly have unspecified other impact via a crafted HID report.

Project: linux
File: hid-cypress.c

static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev);
	unsigned int i;

 	if (!(quirks & CP_RDESC_SWAPPED_MIN_MAX))
 		return rdesc;
 
	if (*rsize < 4)
		return rdesc;

 	for (i = 0; i < *rsize - 4; i++)
 		if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) {
 			rdesc[i] = 0x19;
			rdesc[i + 2] = 0x29;
			swap(rdesc[i + 3], rdesc[i + 1]);
		}
	return rdesc;
}
Commit message: provide a validity check to prevent against Integer overflow conditions (#870)

* provide a validity check to prevent against Integer overflow conditions

* fix some style issues.
CVE: CVE-2017-6952
CWE: CWE-190
Vulnerability description: Integer overflow in the cs_winkernel_malloc function in winkernel_mm.c in Capstone 3.0.4 and earlier allows attackers to cause a denial of service (heap-based buffer overflow in a kernel driver) or possibly have unspecified other impact via a large value.

Project: capstone

void * CAPSTONE_API cs_winkernel_malloc(size_t size)
{
	NT_ASSERT(size);
 
 #pragma prefast(suppress : 30030)		// Allocating executable POOL_TYPE memory
	size_t number_of_bytes = 0;
	CS_WINKERNEL_MEMBLOCK *block = NULL;
	// A specially crafted size value can trigger the overflow.
	// If the sum in a value that overflows or underflows the capacity of the type,
	// the function returns NULL.
	if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(CS_WINKERNEL_MEMBLOCK), &number_of_bytes))) {
		return NULL;
	}
	block = (CS_WINKERNEL_MEMBLOCK *)ExAllocatePoolWithTag(
			NonPagedPool, number_of_bytes, CS_WINKERNEL_POOL_TAG);
 	if (!block) {
 		return NULL;
 	}
	block->size = size;

	return block->data;
}
Commit message: Fixed possible foveon buffer overrun (Secunia SA750000)
CVE: CVE-2017-6890
CWE: CWE-119
Vulnerability description: A boundary error within the "foveon_load_camf()" function (dcraw_foveon.c) when initializing a huffman table in LibRaw-demosaic-pack-GPL2 before 0.18.2 can be exploited to cause a stack-based buffer overflow.

Project: LibRaw-demosaic-pack-GPL2
File: dcraw_foveon.c

 void CLASS foveon_dp_load_raw()
 {
   unsigned c, roff[4], row, col, diff;
  ushort huff[1024], vpred[2][2], hpred[2];
 
   fseek (ifp, 8, SEEK_CUR);
   foveon_huff (huff);
  roff[0] = 48;
  FORC3 roff[c+1] = -(-(roff[c] + get4()) & -16);
  FORC3 {
    fseek (ifp, data_offset+roff[c], SEEK_SET);
    getbits(-1);
    vpred[0][0] = vpred[0][1] = vpred[1][0] = vpred[1][1] = 512;
    for (row=0; row < height; row++) {
#ifdef LIBRAW_LIBRARY_BUILD
    checkCancel();
#endif
      for (col=0; col < width; col++) {
	diff = ljpeg_diff(huff);
	if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
	else hpred[col & 1] += diff;
	image[row*width+col][c] = hpred[col & 1];
      }
    }
  }
}

Project: LibRaw-demosaic-pack-GPL2
File: dcraw_foveon.c

 void CLASS foveon_load_camf()
 {
   unsigned type, wide, high, i, j, row, col, diff;
  ushort huff[1024], vpred[2][2] = {{512,512},{512,512}}, hpred[2];
 
   fseek (ifp, meta_offset, SEEK_SET);
   type = get4();  get4();  get4();
   wide = get4();
   high = get4();
#ifdef LIBRAW_LIBRARY_BUILD
  if(wide>32767 || high > 32767 || wide*high > 20000000)
     throw LIBRAW_EXCEPTION_IO_CORRUPT;
#endif
   if (type == 2) {
     fread (meta_data, 1, meta_length, ifp);
     for (i=0; i < meta_length; i++) {
      high = (high * 1597 + 51749) % 244944;
      wide = high * (INT64) 301593171 >> 24;
      meta_data[i] ^= ((((high << 8) - wide) >> 1) + wide) >> 17;
    }
  } else if (type == 4) {
    free (meta_data);
    meta_data = (char *) malloc (meta_length = wide*high*3/2);
    merror (meta_data, "foveon_load_camf()");
    foveon_huff (huff);
    get4();
    getbits(-1);
    for (j=row=0; row < high; row++) {
      for (col=0; col < wide; col++) {
	diff = ljpeg_diff(huff);
	if (col < 2) hpred[col] = vpred[row & 1][col] += diff;
	else         hpred[col & 1] += diff;
	if (col & 1) {
	  meta_data[j++] = hpred[0] >> 4;
	  meta_data[j++] = hpred[0] << 4 | hpred[1] >> 8;
	  meta_data[j++] = hpred[1];
        }
      }
    }
  } else
    fprintf (stderr,_("%s has unknown CAMF type %d.\n"), ifname, type);
}
Commit message: ucount: Remove the atomicity from ucount->count

Always increment/decrement ucount->count under the ucounts_lock.  The
increments are there already and moving the decrements there means the
locking logic of the code is simpler.  This simplification in the
locking logic fixes a race between put_ucounts and get_ucounts that
could result in a use-after-free because the count could go zero then
be found by get_ucounts and then be freed by put_ucounts.

A bug presumably this one was found by a combination of syzkaller and
KASAN.  JongWhan Kim reported the syzkaller failure and Dmitry Vyukov
spotted the race in the code.

Cc: stable@vger.kernel.org
Fixes: f6b2db1a3e8d ("userns: Make the count of user namespaces per user")
Reported-by: JongHwan Kim <zzoru007@gmail.com>
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Reviewed-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
CVE: CVE-2017-6874
CWE: CWE-416
Vulnerability description: Race condition in kernel/ucount.c in the Linux kernel through 4.10.2 allows local users to cause a denial of service (use-after-free and system crash) or possibly have unspecified other impact via crafted system calls that leverage certain decrement behavior that causes incorrect interaction between put_ucounts and get_ucounts.

Project: linux
File: ucount.c

static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid)
{
	struct hlist_head *hashent = ucounts_hashentry(ns, uid);
	struct ucounts *ucounts, *new;

	spin_lock_irq(&ucounts_lock);
	ucounts = find_ucounts(ns, uid, hashent);
	if (!ucounts) {
		spin_unlock_irq(&ucounts_lock);

		new = kzalloc(sizeof(*new), GFP_KERNEL);
		if (!new)
			return NULL;
 
 		new->ns = ns;
 		new->uid = uid;
		new->count = 0;
 
 		spin_lock_irq(&ucounts_lock);
 		ucounts = find_ucounts(ns, uid, hashent);
		if (ucounts) {
			kfree(new);
		} else {
			hlist_add_head(&new->node, hashent);
 			ucounts = new;
 		}
 	}
	if (ucounts->count == INT_MAX)
 		ucounts = NULL;
	else
		ucounts->count += 1;
 	spin_unlock_irq(&ucounts_lock);
 	return ucounts;
 }

Project: linux
File: ucount.c

static void put_ucounts(struct ucounts *ucounts)
 {
 	unsigned long flags;
 
	spin_lock_irqsave(&ucounts_lock, flags);
	ucounts->count -= 1;
	if (!ucounts->count)
 		hlist_del_init(&ucounts->node);
	else
		ucounts = NULL;
	spin_unlock_irqrestore(&ucounts_lock, flags);
 
	kfree(ucounts);
 }