Commit 378fee2e authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull char/misc fixes from Greg KH:
 "Here are four small char/misc driver fixes for reported issues for
  5.6-rc5.

  These fixes are:

   - binder fix for a potential use-after-free problem found (took two
     tries to get it right)

   - interconnect core fix

   - altera-stapl driver fix

  All four of these have been in linux-next for a while with no reported
  issues"

* tag 'char-misc-5.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc:
  binder: prevent UAF for binderfs devices II
  interconnect: Handle memory allocation errors
  altera-stapl: altera_get_note: prevent write beyond end of 'key'
  binder: prevent UAF for binderfs devices
parents b34e5c13 f0fe2c0f
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -5228,6 +5228,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
		binder_dev = container_of(filp->private_data,
					  struct binder_device, miscdev);
	}
	refcount_inc(&binder_dev->ref);
	proc->context = &binder_dev->context;
	binder_alloc_init(&proc->alloc);

@@ -5405,6 +5406,7 @@ static int binder_node_release(struct binder_node *node, int refs)
static void binder_deferred_release(struct binder_proc *proc)
{
	struct binder_context *context = proc->context;
	struct binder_device *device;
	struct rb_node *n;
	int threads, nodes, incoming_refs, outgoing_refs, active_transactions;

@@ -5421,6 +5423,12 @@ static void binder_deferred_release(struct binder_proc *proc)
		context->binder_context_mgr_node = NULL;
	}
	mutex_unlock(&context->context_mgr_node_lock);
	device = container_of(proc->context, struct binder_device, context);
	if (refcount_dec_and_test(&device->ref)) {
		kfree(context->name);
		kfree(device);
	}
	proc->context = NULL;
	binder_inner_proc_lock(proc);
	/*
	 * Make sure proc stays alive after we
@@ -6077,6 +6085,7 @@ static int __init init_binder_device(const char *name)
	binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
	binder_device->miscdev.name = name;

	refcount_set(&binder_device->ref, 1);
	binder_device->context.binder_context_mgr_uid = INVALID_UID;
	binder_device->context.name = name;
	mutex_init(&binder_device->context.context_mgr_node_lock);
+2 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@
#include <linux/list.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/refcount.h>
#include <linux/stddef.h>
#include <linux/types.h>
#include <linux/uidgid.h>
@@ -33,6 +34,7 @@ struct binder_device {
	struct miscdevice miscdev;
	struct binder_context context;
	struct inode *binderfs_inode;
	refcount_t ref;
};

/**
+5 −2
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
	if (!name)
		goto err;

	refcount_set(&device->ref, 1);
	device->binderfs_inode = inode;
	device->context.binder_context_mgr_uid = INVALID_UID;
	device->context.name = name;
@@ -257,9 +258,11 @@ static void binderfs_evict_inode(struct inode *inode)
	ida_free(&binderfs_minors, device->miscdev.minor);
	mutex_unlock(&binderfs_minors_mutex);

	if (refcount_dec_and_test(&device->ref)) {
		kfree(device->context.name);
		kfree(device);
	}
}

/**
 * binderfs_parse_mount_opts - parse binderfs mount options
+9 −0
Original line number Diff line number Diff line
@@ -445,6 +445,11 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
		path->name = kasprintf(GFP_KERNEL, "%s-%s",
				       src_node->name, dst_node->name);

	if (!path->name) {
		kfree(path);
		return ERR_PTR(-ENOMEM);
	}

	return path;
}
EXPORT_SYMBOL_GPL(of_icc_get);
@@ -579,6 +584,10 @@ struct icc_path *icc_get(struct device *dev, const int src_id, const int dst_id)
	}

	path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name);
	if (!path->name) {
		kfree(path);
		path = ERR_PTR(-ENOMEM);
	}
out:
	mutex_unlock(&icc_lock);
	return path;
+6 −6
Original line number Diff line number Diff line
@@ -2112,8 +2112,8 @@ exit_done:
	return status;
}

static int altera_get_note(u8 *p, s32 program_size,
			s32 *offset, char *key, char *value, int length)
static int altera_get_note(u8 *p, s32 program_size, s32 *offset,
			   char *key, char *value, int keylen, int vallen)
/*
 * Gets key and value of NOTE fields in the JBC file.
 * Can be called in two modes:  if offset pointer is NULL,
@@ -2170,7 +2170,7 @@ static int altera_get_note(u8 *p, s32 program_size,
						&p[note_table + (8 * i) + 4])];

				if (value != NULL)
					strlcpy(value, value_ptr, length);
					strlcpy(value, value_ptr, vallen);

			}
		}
@@ -2189,13 +2189,13 @@ static int altera_get_note(u8 *p, s32 program_size,
				strlcpy(key, &p[note_strings +
						get_unaligned_be32(
						&p[note_table + (8 * i)])],
					length);
					keylen);

			if (value != NULL)
				strlcpy(value, &p[note_strings +
						get_unaligned_be32(
						&p[note_table + (8 * i) + 4])],
					length);
					vallen);

			*offset = i + 1;
		}
@@ -2449,7 +2449,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
			__func__, (format_version == 2) ? "Jam STAPL" :
						"pre-standardized Jam 1.1");
		while (altera_get_note((u8 *)fw->data, fw->size,
					&offset, key, value, 256) == 0)
					&offset, key, value, 32, 256) == 0)
			printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n",
					__func__, key, value);
	}