Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14197d54 authored by Al Viro's avatar Al Viro Committed by David S. Miller
Browse files

[EBTABLES]: Prevent wraparounds in checks for entry components' sizes.

parent 98a0824a
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -338,10 +338,11 @@ ebt_check_match(struct ebt_entry_match *m, struct ebt_entry *e,
   const char *name, unsigned int hookmask, unsigned int *cnt)
{
	struct ebt_match *match;
	size_t left = ((char *)e + e->watchers_offset) - (char *)m;
	int ret;

	if (((char *)m) + m->match_size + sizeof(struct ebt_entry_match) >
	   ((char *)e) + e->watchers_offset)
	if (left < sizeof(struct ebt_entry_match) ||
	    left - sizeof(struct ebt_entry_match) < m->match_size)
		return -EINVAL;
	match = find_match_lock(m->u.name, &ret, &ebt_mutex);
	if (!match)
@@ -367,10 +368,11 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct ebt_entry *e,
   const char *name, unsigned int hookmask, unsigned int *cnt)
{
	struct ebt_watcher *watcher;
	size_t left = ((char *)e + e->target_offset) - (char *)w;
	int ret;

	if (((char *)w) + w->watcher_size + sizeof(struct ebt_entry_watcher) >
	   ((char *)e) + e->target_offset)
	if (left < sizeof(struct ebt_entry_watcher) ||
	   left - sizeof(struct ebt_entry_watcher) < w->watcher_size)
		return -EINVAL;
	watcher = find_watcher_lock(w->u.name, &ret, &ebt_mutex);
	if (!watcher)
@@ -573,6 +575,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
	struct ebt_entry_target *t;
	struct ebt_target *target;
	unsigned int i, j, hook = 0, hookmask = 0;
	size_t gap = e->next_offset - e->target_offset;
	int ret;

	/* don't mess with the struct ebt_entries */
@@ -634,8 +637,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,

	t->u.target = target;
	if (t->u.target == &ebt_standard_target) {
		if (e->target_offset + sizeof(struct ebt_standard_target) >
		   e->next_offset) {
		if (gap < sizeof(struct ebt_standard_target)) {
			BUGPRINT("Standard target size too big\n");
			ret = -EFAULT;
			goto cleanup_watchers;
@@ -646,8 +648,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
			ret = -EFAULT;
			goto cleanup_watchers;
		}
	} else if ((e->target_offset + t->target_size +
	   sizeof(struct ebt_entry_target) > e->next_offset) ||
	} else if (t->target_size > gap - sizeof(struct ebt_entry_target) ||
	   (t->u.target->check &&
	   t->u.target->check(name, hookmask, e, t->data, t->target_size) != 0)){
		module_put(t->u.target->me);