Commit 26873aca authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'driver-core-4.20-rc1' of...

Merge tag 'driver-core-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core updates from Greg KH:
 "Here is a small number of driver core patches for 4.20-rc1.

  Not much happened here this merge window, only a very tiny number of
  patches that do:

   - add BUS_ATTR_WO() for use by drivers

   - component error path fixes

   - kernfs range check fix

   - other tiny error path fixes and const changes

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

* tag 'driver-core-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  devres: provide devm_kstrdup_const()
  mm: move is_kernel_rodata() to asm-generic/sections.h
  devres: constify p in devm_kfree()
  driver core: add BUS_ATTR_WO() macro
  kernfs: Fix range checks in kernfs_get_target_path
  component: fix loop condition to call unbind() if bind() fails
  drivers/base/devtmpfs.c: don't pretend path is const in delete_path
  kernfs: update comment about kernfs_path() return value
parents 9703fc8c 09d1ea1c
...@@ -536,9 +536,9 @@ int component_bind_all(struct device *master_dev, void *data) ...@@ -536,9 +536,9 @@ int component_bind_all(struct device *master_dev, void *data)
} }
if (ret != 0) { if (ret != 0) {
for (; i--; ) for (; i > 0; i--)
if (!master->match->compare[i].duplicate) { if (!master->match->compare[i - 1].duplicate) {
c = master->match->compare[i].component; c = master->match->compare[i - 1].component;
component_unbind(c, master, data); component_unbind(c, master, data);
} }
} }
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/percpu.h> #include <linux/percpu.h>
#include <asm/sections.h>
#include "base.h" #include "base.h"
struct devres_node { struct devres_node {
...@@ -822,6 +824,28 @@ char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) ...@@ -822,6 +824,28 @@ char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp)
} }
EXPORT_SYMBOL_GPL(devm_kstrdup); EXPORT_SYMBOL_GPL(devm_kstrdup);
/**
* devm_kstrdup_const - resource managed conditional string duplication
* @dev: device for which to duplicate the string
* @s: the string to duplicate
* @gfp: the GFP mask used in the kmalloc() call when allocating memory
*
* Strings allocated by devm_kstrdup_const will be automatically freed when
* the associated device is detached.
*
* RETURNS:
* Source string if it is in .rodata section otherwise it falls back to
* devm_kstrdup.
*/
const char *devm_kstrdup_const(struct device *dev, const char *s, gfp_t gfp)
{
if (is_kernel_rodata((unsigned long)s))
return s;
return devm_kstrdup(dev, s, gfp);
}
EXPORT_SYMBOL_GPL(devm_kstrdup_const);
/** /**
* devm_kvasprintf - Allocate resource managed space and format a string * devm_kvasprintf - Allocate resource managed space and format a string
* into that. * into that.
...@@ -885,11 +909,19 @@ EXPORT_SYMBOL_GPL(devm_kasprintf); ...@@ -885,11 +909,19 @@ EXPORT_SYMBOL_GPL(devm_kasprintf);
* *
* Free memory allocated with devm_kmalloc(). * Free memory allocated with devm_kmalloc().
*/ */
void devm_kfree(struct device *dev, void *p) void devm_kfree(struct device *dev, const void *p)
{ {
int rc; int rc;
rc = devres_destroy(dev, devm_kmalloc_release, devm_kmalloc_match, p); /*
* Special case: pointer to a string in .rodata returned by
* devm_kstrdup_const().
*/
if (unlikely(is_kernel_rodata((unsigned long)p)))
return;
rc = devres_destroy(dev, devm_kmalloc_release,
devm_kmalloc_match, (void *)p);
WARN_ON(rc); WARN_ON(rc);
} }
EXPORT_SYMBOL_GPL(devm_kfree); EXPORT_SYMBOL_GPL(devm_kfree);
......
...@@ -252,7 +252,7 @@ static int dev_rmdir(const char *name) ...@@ -252,7 +252,7 @@ static int dev_rmdir(const char *name)
static int delete_path(const char *nodepath) static int delete_path(const char *nodepath)
{ {
const char *path; char *path;
int err = 0; int err = 0;
path = kstrdup(nodepath, GFP_KERNEL); path = kstrdup(nodepath, GFP_KERNEL);
......
...@@ -72,6 +72,9 @@ static int kernfs_get_target_path(struct kernfs_node *parent, ...@@ -72,6 +72,9 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
if (base == kn) if (base == kn)
break; break;
if ((s - path) + 3 >= PATH_MAX)
return -ENAMETOOLONG;
strcpy(s, "../"); strcpy(s, "../");
s += 3; s += 3;
base = base->parent; base = base->parent;
...@@ -88,7 +91,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, ...@@ -88,7 +91,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent,
if (len < 2) if (len < 2)
return -EINVAL; return -EINVAL;
len--; len--;
if ((s - path) + len > PATH_MAX) if ((s - path) + len >= PATH_MAX)
return -ENAMETOOLONG; return -ENAMETOOLONG;
/* reverse fillup of target string from target to base */ /* reverse fillup of target string from target to base */
......
...@@ -141,4 +141,18 @@ static inline bool init_section_intersects(void *virt, size_t size) ...@@ -141,4 +141,18 @@ static inline bool init_section_intersects(void *virt, size_t size)
return memory_intersects(__init_begin, __init_end, virt, size); return memory_intersects(__init_begin, __init_end, virt, size);
} }
/**
* is_kernel_rodata - checks if the pointer address is located in the
* .rodata section
*
* @addr: address to check
*
* Returns: true if the address is located in .rodata, false otherwise.
*/
static inline bool is_kernel_rodata(unsigned long addr)
{
return addr >= (unsigned long)__start_rodata &&
addr < (unsigned long)__end_rodata;
}
#endif /* _ASM_GENERIC_SECTIONS_H_ */ #endif /* _ASM_GENERIC_SECTIONS_H_ */
...@@ -55,6 +55,8 @@ struct bus_attribute { ...@@ -55,6 +55,8 @@ struct bus_attribute {
struct bus_attribute bus_attr_##_name = __ATTR_RW(_name) struct bus_attribute bus_attr_##_name = __ATTR_RW(_name)
#define BUS_ATTR_RO(_name) \ #define BUS_ATTR_RO(_name) \
struct bus_attribute bus_attr_##_name = __ATTR_RO(_name) struct bus_attribute bus_attr_##_name = __ATTR_RO(_name)
#define BUS_ATTR_WO(_name) \
struct bus_attribute bus_attr_##_name = __ATTR_WO(_name)
extern int __must_check bus_create_file(struct bus_type *, extern int __must_check bus_create_file(struct bus_type *,
struct bus_attribute *); struct bus_attribute *);
...@@ -692,8 +694,10 @@ static inline void *devm_kcalloc(struct device *dev, ...@@ -692,8 +694,10 @@ static inline void *devm_kcalloc(struct device *dev,
{ {
return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO); return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
} }
extern void devm_kfree(struct device *dev, void *p); extern void devm_kfree(struct device *dev, const void *p);
extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc; extern char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) __malloc;
extern const char *devm_kstrdup_const(struct device *dev,
const char *s, gfp_t gfp);
extern void *devm_kmemdup(struct device *dev, const void *src, size_t len, extern void *devm_kmemdup(struct device *dev, const void *src, size_t len,
gfp_t gfp); gfp_t gfp);
......
...@@ -477,10 +477,11 @@ static inline void kernfs_init(void) { } ...@@ -477,10 +477,11 @@ static inline void kernfs_init(void) { }
* @buf: buffer to copy @kn's name into * @buf: buffer to copy @kn's name into
* @buflen: size of @buf * @buflen: size of @buf
* *
* Builds and returns the full path of @kn in @buf of @buflen bytes. The * If @kn is NULL result will be "(null)".
* path is built from the end of @buf so the returned pointer usually *
* doesn't match @buf. If @buf isn't long enough, @buf is nul terminated * Returns the length of the full path. If the full length is equal to or
* and %NULL is returned. * greater than @buflen, @buf contains the truncated path with the trailing
* '\0'. On error, -errno is returned.
*/ */
static inline int kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen) static inline int kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
{ {
......
...@@ -15,17 +15,10 @@ ...@@ -15,17 +15,10 @@
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/userfaultfd_k.h> #include <linux/userfaultfd_k.h>
#include <asm/sections.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include "internal.h" #include "internal.h"
static inline int is_kernel_rodata(unsigned long addr)
{
return addr >= (unsigned long)__start_rodata &&
addr < (unsigned long)__end_rodata;
}
/** /**
* kfree_const - conditionally free memory * kfree_const - conditionally free memory
* @x: pointer to the memory * @x: pointer to the memory
......
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