Commit 378fee2e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'char-misc-5.6-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc

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
...@@ -5228,6 +5228,7 @@ static int binder_open(struct inode *nodp, struct file *filp) ...@@ -5228,6 +5228,7 @@ static int binder_open(struct inode *nodp, struct file *filp)
binder_dev = container_of(filp->private_data, binder_dev = container_of(filp->private_data,
struct binder_device, miscdev); struct binder_device, miscdev);
} }
refcount_inc(&binder_dev->ref);
proc->context = &binder_dev->context; proc->context = &binder_dev->context;
binder_alloc_init(&proc->alloc); binder_alloc_init(&proc->alloc);
...@@ -5405,6 +5406,7 @@ static int binder_node_release(struct binder_node *node, int refs) ...@@ -5405,6 +5406,7 @@ static int binder_node_release(struct binder_node *node, int refs)
static void binder_deferred_release(struct binder_proc *proc) static void binder_deferred_release(struct binder_proc *proc)
{ {
struct binder_context *context = proc->context; struct binder_context *context = proc->context;
struct binder_device *device;
struct rb_node *n; struct rb_node *n;
int threads, nodes, incoming_refs, outgoing_refs, active_transactions; int threads, nodes, incoming_refs, outgoing_refs, active_transactions;
...@@ -5421,6 +5423,12 @@ static void binder_deferred_release(struct binder_proc *proc) ...@@ -5421,6 +5423,12 @@ static void binder_deferred_release(struct binder_proc *proc)
context->binder_context_mgr_node = NULL; context->binder_context_mgr_node = NULL;
} }
mutex_unlock(&context->context_mgr_node_lock); 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); binder_inner_proc_lock(proc);
/* /*
* Make sure proc stays alive after we * Make sure proc stays alive after we
...@@ -6077,6 +6085,7 @@ static int __init init_binder_device(const char *name) ...@@ -6077,6 +6085,7 @@ static int __init init_binder_device(const char *name)
binder_device->miscdev.minor = MISC_DYNAMIC_MINOR; binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
binder_device->miscdev.name = name; binder_device->miscdev.name = name;
refcount_set(&binder_device->ref, 1);
binder_device->context.binder_context_mgr_uid = INVALID_UID; binder_device->context.binder_context_mgr_uid = INVALID_UID;
binder_device->context.name = name; binder_device->context.name = name;
mutex_init(&binder_device->context.context_mgr_node_lock); mutex_init(&binder_device->context.context_mgr_node_lock);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/refcount.h>
#include <linux/stddef.h> #include <linux/stddef.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/uidgid.h> #include <linux/uidgid.h>
...@@ -33,6 +34,7 @@ struct binder_device { ...@@ -33,6 +34,7 @@ struct binder_device {
struct miscdevice miscdev; struct miscdevice miscdev;
struct binder_context context; struct binder_context context;
struct inode *binderfs_inode; struct inode *binderfs_inode;
refcount_t ref;
}; };
/** /**
......
...@@ -154,6 +154,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode, ...@@ -154,6 +154,7 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
if (!name) if (!name)
goto err; goto err;
refcount_set(&device->ref, 1);
device->binderfs_inode = inode; device->binderfs_inode = inode;
device->context.binder_context_mgr_uid = INVALID_UID; device->context.binder_context_mgr_uid = INVALID_UID;
device->context.name = name; device->context.name = name;
...@@ -257,8 +258,10 @@ static void binderfs_evict_inode(struct inode *inode) ...@@ -257,8 +258,10 @@ static void binderfs_evict_inode(struct inode *inode)
ida_free(&binderfs_minors, device->miscdev.minor); ida_free(&binderfs_minors, device->miscdev.minor);
mutex_unlock(&binderfs_minors_mutex); mutex_unlock(&binderfs_minors_mutex);
if (refcount_dec_and_test(&device->ref)) {
kfree(device->context.name); kfree(device->context.name);
kfree(device); kfree(device);
}
} }
/** /**
......
...@@ -445,6 +445,11 @@ struct icc_path *of_icc_get(struct device *dev, const char *name) ...@@ -445,6 +445,11 @@ struct icc_path *of_icc_get(struct device *dev, const char *name)
path->name = kasprintf(GFP_KERNEL, "%s-%s", path->name = kasprintf(GFP_KERNEL, "%s-%s",
src_node->name, dst_node->name); src_node->name, dst_node->name);
if (!path->name) {
kfree(path);
return ERR_PTR(-ENOMEM);
}
return path; return path;
} }
EXPORT_SYMBOL_GPL(of_icc_get); 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) ...@@ -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); path->name = kasprintf(GFP_KERNEL, "%s-%s", src->name, dst->name);
if (!path->name) {
kfree(path);
path = ERR_PTR(-ENOMEM);
}
out: out:
mutex_unlock(&icc_lock); mutex_unlock(&icc_lock);
return path; return path;
......
...@@ -2112,8 +2112,8 @@ static int altera_execute(struct altera_state *astate, ...@@ -2112,8 +2112,8 @@ static int altera_execute(struct altera_state *astate,
return status; return status;
} }
static int altera_get_note(u8 *p, s32 program_size, static int altera_get_note(u8 *p, s32 program_size, s32 *offset,
s32 *offset, char *key, char *value, int length) char *key, char *value, int keylen, int vallen)
/* /*
* Gets key and value of NOTE fields in the JBC file. * Gets key and value of NOTE fields in the JBC file.
* Can be called in two modes: if offset pointer is NULL, * 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, ...@@ -2170,7 +2170,7 @@ static int altera_get_note(u8 *p, s32 program_size,
&p[note_table + (8 * i) + 4])]; &p[note_table + (8 * i) + 4])];
if (value != NULL) 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, ...@@ -2189,13 +2189,13 @@ static int altera_get_note(u8 *p, s32 program_size,
strlcpy(key, &p[note_strings + strlcpy(key, &p[note_strings +
get_unaligned_be32( get_unaligned_be32(
&p[note_table + (8 * i)])], &p[note_table + (8 * i)])],
length); keylen);
if (value != NULL) if (value != NULL)
strlcpy(value, &p[note_strings + strlcpy(value, &p[note_strings +
get_unaligned_be32( get_unaligned_be32(
&p[note_table + (8 * i) + 4])], &p[note_table + (8 * i) + 4])],
length); vallen);
*offset = i + 1; *offset = i + 1;
} }
...@@ -2449,7 +2449,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw) ...@@ -2449,7 +2449,7 @@ int altera_init(struct altera_config *config, const struct firmware *fw)
__func__, (format_version == 2) ? "Jam STAPL" : __func__, (format_version == 2) ? "Jam STAPL" :
"pre-standardized Jam 1.1"); "pre-standardized Jam 1.1");
while (altera_get_note((u8 *)fw->data, fw->size, 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", printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n",
__func__, key, value); __func__, key, value);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment