Page MenuHomeFreeBSD

Fix for improper bound checking on cn_namelen
Needs ReviewPublic

Authored by cturt_hardenedbsd.org on Mar 16 2016, 8:31 PM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

The cn_namelen member is a signed type.

sys/sys/namei.h:

struct componentname {
	...
	long	cn_namelen;	/* length of looked up component */
};

There are no casts to unsigned for any of the values it is compared against:

sys/kern/uipc_mqueue.c:

#define	MQFS_NAMELEN		NAME_MAX

sys/sys/syslimits.h:

#define	NAME_MAX		  255	/* max bytes in a file name */

sys/fs/pseudofs/pseudofs.h:

#define PFS_NAMELEN		24

Since signed comparisons will be used, negative lengths will be incorrectly accepted, which could lead to out of bounds reads in later parts of the code. For example in mqfs_search:

sys/kern/uipc_mqueue.c:

static struct mqfs_node *
mqfs_search(struct mqfs_node *pd, const char *name, int len)
{
	struct mqfs_node *pn;

	sx_assert(&pd->mn_info->mi_lock, SX_LOCKED);
	LIST_FOREACH(pn, &pd->mn_children, mn_sibling) {
		if (strncmp(pn->mn_name, name, len) == 0 &&
		    pn->mn_name[len] == '\0')
			return (pn);
	}
	return (NULL);
}

However, there is more serious potential if this negative length were to be passed to mqfs_create_node:

sys/kern/uipc_mqueue.c:

static __inline struct mqfs_node *
mqnode_alloc(void)
{
	return uma_zalloc(mqnode_zone, M_WAITOK | M_ZERO);
}

static struct mqfs_node *
mqfs_create_node(const char *name, int namelen, struct ucred *cred, int mode,
	int nodetype)
{
	struct mqfs_node *node;

	node = mqnode_alloc();
	strncpy(node->mn_name, name, namelen);
	node->mn_type = nodetype;
	node->mn_refcount = 1;
	vfs_timestamp(&node->mn_birth);
	node->mn_ctime = node->mn_atime = node->mn_mtime
		= node->mn_birth;
	node->mn_uid = cred->cr_uid;
	node->mn_gid = cred->cr_gid;
	node->mn_mode = mode;
	return (node);
}

Negative namelen will be converted to unsigned for strcpy which would then overflow fixed buffer:

sys/kern/uipc_mqueue.c:

struct mqfs_node {
	char			mn_name[MQFS_NAMELEN+1];
	...

Diff Detail

Repository
rS FreeBSD src repository - subversion
Lint
Lint Skipped
Unit
Unit Tests Skipped