Ejemplo n.º 1
0
/*
 * Verify redzones.
 * This function is called on free() and realloc().
 */
void
redzone_check(caddr_t naddr)
{
	struct stack ast, fst;
	caddr_t haddr, faddr;
	u_int ncorruptions;
	u_long nsize;
	int i;

	haddr = naddr - REDZONE_HSIZE;
	bcopy(haddr, &ast, sizeof(ast));
	haddr += sizeof(ast);
	bcopy(haddr, &nsize, sizeof(nsize));
	haddr += sizeof(nsize);

	atomic_subtract_long(&redzone_extra_mem,
	    redzone_size_ntor(nsize) - nsize);

	/* Look for buffer underflow. */
	ncorruptions = 0;
	for (i = 0; i < REDZONE_CHSIZE; i++, haddr++) {
		if (*(u_char *)haddr != 0x42)
			ncorruptions++;
	}
	if (ncorruptions > 0) {
		printf("REDZONE: Buffer underflow detected. %u byte%s "
		    "corrupted before %p (%lu bytes allocated).\n",
		    ncorruptions, ncorruptions == 1 ? "" : "s", naddr, nsize);
		printf("Allocation backtrace:\n");
		stack_print_ddb(&ast);
		printf("Free backtrace:\n");
		stack_save(&fst);
		stack_print_ddb(&fst);
		if (redzone_panic)
			panic("Stopping here.");
	}
	faddr = naddr + nsize;
	/* Look for buffer overflow. */
	ncorruptions = 0;
	for (i = 0; i < REDZONE_CFSIZE; i++, faddr++) {
		if (*(u_char *)faddr != 0x42)
			ncorruptions++;
	}
	if (ncorruptions > 0) {
		printf("REDZONE: Buffer overflow detected. %u byte%s corrupted "
		    "after %p (%lu bytes allocated).\n", ncorruptions,
		    ncorruptions == 1 ? "" : "s", naddr + nsize, nsize);
		printf("Allocation backtrace:\n");
		stack_print_ddb(&ast);
		printf("Free backtrace:\n");
		stack_save(&fst);
		stack_print_ddb(&fst);
		if (redzone_panic)
			panic("Stopping here.");
	}
}
Ejemplo n.º 2
0
/*
 * Drop data from (the front of) a sockbuf.  If the current record is
 * exhausted this routine will move onto the next one and continue dropping
 * data.
 */
void
sbdrop(struct sockbuf *sb, int len)
{
	struct mbuf *m;
	struct mbuf *free_chain = NULL;

	sbcheck(sb);
	crit_enter();

	m = sb->sb_mb;
	while (m && len > 0) {
		if (m->m_len > len) {
			m->m_len -= len;
			m->m_data += len;
			sb->sb_cc -= len;
			atomic_subtract_long(&sb->sb_cc_prealloc, len);
			break;
		}
		len -= m->m_len;
		m = sbunlinkmbuf(sb, m, &free_chain);
		if (m == NULL && len)
			m = sb->sb_mb;
	}

	/*
	 * Remove any trailing 0-length mbufs in the current record.  If
	 * the last record for which data was removed is now empty, m will be
	 * NULL.
	 */
	while (m && m->m_len == 0) {
		m = sbunlinkmbuf(sb, m, &free_chain);
	}
	crit_exit();
	if (free_chain)
		m_freem(free_chain);
	sbcheck(sb);
}
Ejemplo n.º 3
0
/*
 * Compress mbuf chain m into the socket buffer sb following mbuf tailm.
 * If tailm is null, the buffer is presumed empty.  Also, as a side-effect,
 * increment the sockbuf counts for each mbuf in the chain.
 */
void
sbcompress(struct sockbuf *sb, struct mbuf *m, struct mbuf *tailm)
{
	int eor = 0;
	struct mbuf *free_chain = NULL;

	mbuftrackid(m, 23);

	sbcheck(sb);
	while (m) {
		struct mbuf *o;

		eor |= m->m_flags & M_EOR;
		/*
		 * Disregard empty mbufs as long as we don't encounter
		 * an end-of-record or there is a trailing mbuf of
		 * the same type to propagate the EOR flag to.
		 *
		 * Defer the m_free() call because it can block and break
		 * the atomicy of the sockbuf.
		 */
		if (m->m_len == 0 &&
		    (eor == 0 ||
		     (((o = m->m_next) || (o = tailm)) &&
		      o->m_type == m->m_type))) {
			o = m->m_next;
			m->m_next = free_chain;
			free_chain = m;
			m = o;
			continue;
		}

		/* See if we can coalesce with preceding mbuf. */
		if (tailm && !(tailm->m_flags & M_EOR) && M_WRITABLE(tailm) &&
		    m->m_len <= MCLBYTES / 4 && /* XXX: Don't copy too much */
		    m->m_len <= M_TRAILINGSPACE(tailm) &&
		    tailm->m_type == m->m_type) {
			u_long mbcnt_sz;

			bcopy(mtod(m, caddr_t),
			      mtod(tailm, caddr_t) + tailm->m_len,
			      (unsigned)m->m_len);
			tailm->m_len += m->m_len;

			sb->sb_cc += m->m_len;		/* update sb counter */

			/*
			 * Fix the wrongly updated mbcnt_prealloc
			 */
			mbcnt_sz = MSIZE;
			if (m->m_flags & M_EXT)
				mbcnt_sz += m->m_ext.ext_size;
			atomic_subtract_long(&sb->sb_mbcnt_prealloc, mbcnt_sz);

			o = m->m_next;
			m->m_next = free_chain;
			free_chain = m;
			m = o;
			continue;
		}

		/* Insert whole mbuf. */
		if (tailm == NULL) {
			KASSERT(sb->sb_mb == NULL,
				("sbcompress: sb_mb not NULL"));
			sb->sb_mb = m;		/* only mbuf in sockbuf */
			sb->sb_lastrecord = m;	/* new last record */
		} else {
			tailm->m_next = m;	/* tack m on following tailm */
		}
		sb->sb_lastmbuf = m;	/* update last mbuf hint */

		tailm = m;	/* just inserted mbuf becomes the new tail */
		m = m->m_next;		/* advance to next mbuf */
		tailm->m_next = NULL;	/* split inserted mbuf off from chain */

		/* update sb counters for just added mbuf */
		sballoc(sb, tailm);

		/* clear EOR on intermediate mbufs */
		tailm->m_flags &= ~M_EOR;
	}

	/*
	 * Propogate EOR to the last mbuf
	 */
	if (eor) {
		if (tailm)
			tailm->m_flags |= eor;
		else
			kprintf("semi-panic: sbcompress");
	}

	/*
	 * Clean up any defered frees.
	 */
	while (free_chain)
		free_chain = m_free(free_chain);

	sbcheck(sb);
}