whiterose

linux unikernel
Log | Files | Refs | README | LICENSE | git clone https://git.ne02ptzero.me/git/whiterose

commit 26873acacbdbb4e4b444f5dd28dcc4853f0e8ba2
parent 9703fc8caf36ac65dca1538b23dd137de0b53233
Author: Linus Torvalds <torvalds@linux-foundation.org>
Date:   Fri, 26 Oct 2018 08:42:25 -0700

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

Diffstat:
Mdrivers/base/component.c | 6+++---
Mdrivers/base/devres.c | 36++++++++++++++++++++++++++++++++++--
Mdrivers/base/devtmpfs.c | 2+-
Mfs/kernfs/symlink.c | 5++++-
Minclude/asm-generic/sections.h | 14++++++++++++++
Minclude/linux/device.h | 6+++++-
Minclude/linux/kernfs.h | 9+++++----
Mmm/util.c | 7-------
8 files changed, 66 insertions(+), 19 deletions(-)

diff --git a/drivers/base/component.c b/drivers/base/component.c @@ -536,9 +536,9 @@ int component_bind_all(struct device *master_dev, void *data) } 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); } } diff --git a/drivers/base/devres.c b/drivers/base/devres.c @@ -11,6 +11,8 @@ #include <linux/slab.h> #include <linux/percpu.h> +#include <asm/sections.h> + #include "base.h" struct devres_node { @@ -823,6 +825,28 @@ char *devm_kstrdup(struct device *dev, const char *s, gfp_t gfp) 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 * into that. * @dev: Device to allocate memory for @@ -885,11 +909,19 @@ EXPORT_SYMBOL_GPL(devm_kasprintf); * * 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; - 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); } EXPORT_SYMBOL_GPL(devm_kfree); diff --git a/drivers/base/devtmpfs.c b/drivers/base/devtmpfs.c @@ -252,7 +252,7 @@ static int dev_rmdir(const char *name) static int delete_path(const char *nodepath) { - const char *path; + char *path; int err = 0; path = kstrdup(nodepath, GFP_KERNEL); diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c @@ -72,6 +72,9 @@ static int kernfs_get_target_path(struct kernfs_node *parent, if (base == kn) break; + if ((s - path) + 3 >= PATH_MAX) + return -ENAMETOOLONG; + strcpy(s, "../"); s += 3; base = base->parent; @@ -88,7 +91,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, if (len < 2) return -EINVAL; len--; - if ((s - path) + len > PATH_MAX) + if ((s - path) + len >= PATH_MAX) return -ENAMETOOLONG; /* reverse fillup of target string from target to base */ diff --git a/include/asm-generic/sections.h b/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); } +/** + * 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_ */ diff --git a/include/linux/device.h b/include/linux/device.h @@ -55,6 +55,8 @@ struct bus_attribute { struct bus_attribute bus_attr_##_name = __ATTR_RW(_name) #define BUS_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 *, 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); } -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 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, gfp_t gfp); diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h @@ -477,10 +477,11 @@ static inline void kernfs_init(void) { } * @buf: buffer to copy @kn's name into * @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) { diff --git a/mm/util.c b/mm/util.c @@ -15,17 +15,10 @@ #include <linux/vmalloc.h> #include <linux/userfaultfd_k.h> -#include <asm/sections.h> #include <linux/uaccess.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 * @x: pointer to the memory