Browse Source

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
Linus Torvalds 6 years ago
parent
commit
26873acacb

+ 3 - 3
drivers/base/component.c

@@ -536,9 +536,9 @@ int component_bind_all(struct device *master_dev, void *data)
 		}
 		}
 
 
 	if (ret != 0) {
 	if (ret != 0) {
-		for (; i--; )
-			if (!master->match->compare[i].duplicate) {
-				c = master->match->compare[i].component;
+		for (; i > 0; i--)
+			if (!master->match->compare[i - 1].duplicate) {
+				c = master->match->compare[i - 1].component;
 				component_unbind(c, master, data);
 				component_unbind(c, master, data);
 			}
 			}
 	}
 	}

+ 34 - 2
drivers/base/devres.c

@@ -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)
 }
 }
 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);
  *
  *
  * 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);

+ 1 - 1
drivers/base/devtmpfs.c

@@ -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);

+ 4 - 1
fs/kernfs/symlink.c

@@ -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,
 	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 */

+ 14 - 0
include/asm-generic/sections.h

@@ -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_ */

+ 5 - 1
include/linux/device.h

@@ -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,
 {
 {
 	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);
 
 

+ 5 - 4
include/linux/kernfs.h

@@ -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
- * 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
- * and %NULL is returned.
+ * If @kn is NULL result will be "(null)".
+ *
+ * Returns the length of the full path.  If the full length is equal to or
+ * 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)
 {
 {

+ 0 - 7
mm/util.c

@@ -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