btrfs: fix race between quota disable and quota assign ioctls
[platform/kernel/linux-rpi.git] / lib / vsprintf.c
index d7ad44f..a60f0bb 100644 (file)
 
 #include <asm/page.h>          /* for PAGE_SIZE */
 #include <asm/byteorder.h>     /* cpu_to_le16 */
+#include <asm/unaligned.h>
 
 #include <linux/string_helpers.h>
 #include "kstrtox.h"
 
-static unsigned long long simple_strntoull(const char *startp, size_t max_chars,
-                                          char **endp, unsigned int base)
+/* Disable pointer hashing if requested */
+bool no_hash_pointers __ro_after_init;
+EXPORT_SYMBOL_GPL(no_hash_pointers);
+
+static noinline unsigned long long simple_strntoull(const char *startp, size_t max_chars, char **endp, unsigned int base)
 {
        const char *cp;
        unsigned long long result = 0ULL;
@@ -757,14 +761,16 @@ static void enable_ptr_key_workfn(struct work_struct *work)
 
 static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
 
-static void fill_random_ptr_key(struct random_ready_callback *unused)
+static int fill_random_ptr_key(struct notifier_block *nb,
+                              unsigned long action, void *data)
 {
        /* This may be in an interrupt handler. */
        queue_work(system_unbound_wq, &enable_ptr_key_work);
+       return 0;
 }
 
-static struct random_ready_callback random_ready = {
-       .func = fill_random_ptr_key
+static struct notifier_block random_ready = {
+       .notifier_call = fill_random_ptr_key
 };
 
 static int __init initialize_ptr_random(void)
@@ -778,7 +784,7 @@ static int __init initialize_ptr_random(void)
                return 0;
        }
 
-       ret = add_random_ready_callback(&random_ready);
+       ret = register_random_ready_notifier(&random_ready);
        if (!ret) {
                return 0;
        } else if (ret == -EALREADY) {
@@ -848,6 +854,19 @@ static char *ptr_to_id(char *buf, char *end, const void *ptr,
        return pointer_string(buf, end, (const void *)hashval, spec);
 }
 
+static char *default_pointer(char *buf, char *end, const void *ptr,
+                            struct printf_spec spec)
+{
+       /*
+        * default is to _not_ leak addresses, so hash before printing,
+        * unless no_hash_pointers is specified on the command line.
+        */
+       if (unlikely(no_hash_pointers))
+               return pointer_string(buf, end, ptr, spec);
+
+       return ptr_to_id(buf, end, ptr, spec);
+}
+
 int kptr_restrict __read_mostly;
 
 static noinline_for_stack
@@ -857,7 +876,7 @@ char *restricted_pointer(char *buf, char *end, const void *ptr,
        switch (kptr_restrict) {
        case 0:
                /* Handle as %p, hash and do _not_ leak addresses. */
-               return ptr_to_id(buf, end, ptr, spec);
+               return default_pointer(buf, end, ptr, spec);
        case 1: {
                const struct cred *cred;
 
@@ -1771,7 +1790,7 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
        char output[sizeof("0123 little-endian (0x01234567)")];
        char *p = output;
        unsigned int i;
-       u32 val;
+       u32 orig, val;
 
        if (fmt[1] != 'c' || fmt[2] != 'c')
                return error_string(buf, end, "(%p4?)", spec);
@@ -1779,21 +1798,22 @@ char *fourcc_string(char *buf, char *end, const u32 *fourcc,
        if (check_pointer(&buf, end, fourcc, spec))
                return buf;
 
-       val = *fourcc & ~BIT(31);
+       orig = get_unaligned(fourcc);
+       val = orig & ~BIT(31);
 
-       for (i = 0; i < sizeof(*fourcc); i++) {
+       for (i = 0; i < sizeof(u32); i++) {
                unsigned char c = val >> (i * 8);
 
                /* Print non-control ASCII characters as-is, dot otherwise */
                *p++ = isascii(c) && isprint(c) ? c : '.';
        }
 
-       strcpy(p, *fourcc & BIT(31) ? " big-endian" : " little-endian");
+       strcpy(p, orig & BIT(31) ? " big-endian" : " little-endian");
        p += strlen(p);
 
        *p++ = ' ';
        *p++ = '(';
-       p = special_hex_number(p, output + sizeof(output) - 2, *fourcc, sizeof(u32));
+       p = special_hex_number(p, output + sizeof(output) - 2, orig, sizeof(u32));
        *p++ = ')';
        *p = '\0';
 
@@ -2225,10 +2245,6 @@ char *fwnode_string(char *buf, char *end, struct fwnode_handle *fwnode,
        return widen_string(buf, buf - buf_start, end, spec);
 }
 
-/* Disable pointer hashing if requested */
-bool no_hash_pointers __ro_after_init;
-EXPORT_SYMBOL_GPL(no_hash_pointers);
-
 int __init no_hash_pointers_enable(char *str)
 {
        if (no_hash_pointers)
@@ -2457,7 +2473,7 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
        case 'e':
                /* %pe with a non-ERR_PTR gets treated as plain %p */
                if (!IS_ERR(ptr))
-                       break;
+                       return default_pointer(buf, end, ptr, spec);
                return err_ptr(buf, end, ptr, spec);
        case 'u':
        case 'k':
@@ -2467,16 +2483,9 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
                default:
                        return error_string(buf, end, "(einval)", spec);
                }
+       default:
+               return default_pointer(buf, end, ptr, spec);
        }
-
-       /*
-        * default is to _not_ leak addresses, so hash before printing,
-        * unless no_hash_pointers is specified on the command line.
-        */
-       if (unlikely(no_hash_pointers))
-               return pointer_string(buf, end, ptr, spec);
-       else
-               return ptr_to_id(buf, end, ptr, spec);
 }
 
 /*