mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
Merge branch 'akpm' (patches from Andrew)
Merge yet more updates from Andrew Morton: - lots of little subsystems - a few post-linux-next MM material. Most of the rest awaits more merging of other trees. Subsystems affected by this series: alpha, procfs, misc, core-kernel, bitmap, lib, lz4, checkpatch, nilfs, kdump, rapidio, gcov, bfs, relay, resource, ubsan, reboot, fault-injection, lzo, apparmor, and mm (swap, memory-hotplug, pagemap, cleanups, and gup). * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (86 commits) mm: fix some spelling mistakes in comments mm: simplify follow_pte{,pmd} mm: unexport follow_pte_pmd apparmor: remove duplicate macro list_entry_is_head() lib/lzo/lzo1x_compress.c: make lzogeneric1x_1_compress() static fault-injection: handle EI_ETYPE_TRUE reboot: hide from sysfs not applicable settings reboot: allow to override reboot type if quirks are found reboot: remove cf9_safe from allowed types and rename cf9_force reboot: allow to specify reboot mode via sysfs reboot: refactor and comment the cpu selection code lib/ubsan.c: mark type_check_kinds with static keyword kcov: don't instrument with UBSAN ubsan: expand tests and reporting ubsan: remove UBSAN_MISC in favor of individual options ubsan: enable for all*config builds ubsan: disable UBSAN_TRAP for all*config ubsan: disable object-size sanitizer under GCC ubsan: move cc-option tests into Kconfig ubsan: remove redundant -Wno-maybe-uninitialized ...
This commit is contained in:
commit
f986e35083
32
Documentation/ABI/testing/sysfs-kernel-reboot
Normal file
32
Documentation/ABI/testing/sysfs-kernel-reboot
Normal file
@ -0,0 +1,32 @@
|
||||
What: /sys/kernel/reboot
|
||||
Date: November 2020
|
||||
KernelVersion: 5.11
|
||||
Contact: Matteo Croce <mcroce@microsoft.com>
|
||||
Description: Interface to set the kernel reboot behavior, similarly to
|
||||
what can be done via the reboot= cmdline option.
|
||||
(see Documentation/admin-guide/kernel-parameters.txt)
|
||||
|
||||
What: /sys/kernel/reboot/mode
|
||||
Date: November 2020
|
||||
KernelVersion: 5.11
|
||||
Contact: Matteo Croce <mcroce@microsoft.com>
|
||||
Description: Reboot mode. Valid values are: cold warm hard soft gpio
|
||||
|
||||
What: /sys/kernel/reboot/type
|
||||
Date: November 2020
|
||||
KernelVersion: 5.11
|
||||
Contact: Matteo Croce <mcroce@microsoft.com>
|
||||
Description: Reboot type. Valid values are: bios acpi kbd triple efi pci
|
||||
|
||||
What: /sys/kernel/reboot/cpu
|
||||
Date: November 2020
|
||||
KernelVersion: 5.11
|
||||
Contact: Matteo Croce <mcroce@microsoft.com>
|
||||
Description: CPU number to use to reboot.
|
||||
|
||||
What: /sys/kernel/reboot/force
|
||||
Date: November 2020
|
||||
KernelVersion: 5.11
|
||||
Contact: Matteo Croce <mcroce@microsoft.com>
|
||||
Description: Don't wait for any other CPUs on reboot and
|
||||
avoid anything that could hang.
|
@ -39,6 +39,12 @@ call.
|
||||
User-space tools can get the kernel name, host name, kernel release
|
||||
number, kernel version, architecture name and OS type from it.
|
||||
|
||||
(uts_namespace, name)
|
||||
---------------------
|
||||
|
||||
Offset of the name's member. Crash Utility and Makedumpfile get
|
||||
the start address of the init_uts_ns.name from this.
|
||||
|
||||
node_online_map
|
||||
---------------
|
||||
|
||||
|
@ -86,3 +86,4 @@ References
|
||||
|
||||
.. _1: https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Debugging-Options.html
|
||||
.. _2: https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html
|
||||
.. _3: https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html
|
||||
|
@ -210,6 +210,7 @@ read the file /proc/PID/status::
|
||||
NoNewPrivs: 0
|
||||
Seccomp: 0
|
||||
Speculation_Store_Bypass: thread vulnerable
|
||||
SpeculationIndirectBranch: conditional enabled
|
||||
voluntary_ctxt_switches: 0
|
||||
nonvoluntary_ctxt_switches: 1
|
||||
|
||||
@ -292,6 +293,7 @@ It's slow but very precise.
|
||||
NoNewPrivs no_new_privs, like prctl(PR_GET_NO_NEW_PRIV, ...)
|
||||
Seccomp seccomp mode, like prctl(PR_GET_SECCOMP, ...)
|
||||
Speculation_Store_Bypass speculative store bypass mitigation status
|
||||
SpeculationIndirectBranch indirect branch speculation mode
|
||||
Cpus_allowed mask of CPUs on which this process may run
|
||||
Cpus_allowed_list Same as previous, but in "list format"
|
||||
Mems_allowed mask of memory nodes allowed to this process
|
||||
|
@ -134,7 +134,7 @@ common_shutdown_1(void *generic_ptr)
|
||||
#ifdef CONFIG_DUMMY_CONSOLE
|
||||
/* If we've gotten here after SysRq-b, leave interrupt
|
||||
context before taking over the console. */
|
||||
if (in_interrupt())
|
||||
if (in_irq())
|
||||
irq_exit();
|
||||
/* This has the effect of resetting the VGA video origin. */
|
||||
console_lock();
|
||||
|
@ -313,6 +313,10 @@ SECTIONS
|
||||
#else
|
||||
.data : AT(ADDR(.data) - LOAD_OFFSET) {
|
||||
DATA_DATA
|
||||
#ifdef CONFIG_UBSAN
|
||||
*(.data..Lubsan_data*)
|
||||
*(.data..Lubsan_type*)
|
||||
#endif
|
||||
*(.data.rel*)
|
||||
*(.toc1)
|
||||
*(.branch_lt)
|
||||
|
@ -170,7 +170,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_write, unsigned long, mmio_addr,
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto out_unlock_mmap;
|
||||
|
||||
ret = follow_pte_pmd(vma->vm_mm, mmio_addr, NULL, &ptep, NULL, &ptl);
|
||||
ret = follow_pte(vma->vm_mm, mmio_addr, NULL, &ptep, NULL, &ptl);
|
||||
if (ret)
|
||||
goto out_unlock_mmap;
|
||||
|
||||
@ -311,7 +311,7 @@ SYSCALL_DEFINE3(s390_pci_mmio_read, unsigned long, mmio_addr,
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
goto out_unlock_mmap;
|
||||
|
||||
ret = follow_pte_pmd(vma->vm_mm, mmio_addr, NULL, &ptep, NULL, &ptl);
|
||||
ret = follow_pte(vma->vm_mm, mmio_addr, NULL, &ptep, NULL, &ptl);
|
||||
if (ret)
|
||||
goto out_unlock_mmap;
|
||||
|
||||
|
@ -134,7 +134,7 @@ static int remove_buf_file_callback(struct dentry *dentry)
|
||||
}
|
||||
|
||||
/* relay channel callbacks */
|
||||
static struct rchan_callbacks relay_callbacks = {
|
||||
static const struct rchan_callbacks relay_callbacks = {
|
||||
.subbuf_start = subbuf_start_callback,
|
||||
.create_buf_file = create_buf_file_callback,
|
||||
.remove_buf_file = remove_buf_file_callback,
|
||||
|
@ -10,6 +10,7 @@ lkdtm-$(CONFIG_LKDTM) += rodata_objcopy.o
|
||||
lkdtm-$(CONFIG_LKDTM) += usercopy.o
|
||||
lkdtm-$(CONFIG_LKDTM) += stackleak.o
|
||||
lkdtm-$(CONFIG_LKDTM) += cfi.o
|
||||
lkdtm-$(CONFIG_LKDTM) += fortify.o
|
||||
|
||||
KASAN_SANITIZE_rodata.o := n
|
||||
KASAN_SANITIZE_stackleak.o := n
|
||||
|
@ -482,3 +482,53 @@ noinline void lkdtm_CORRUPT_PAC(void)
|
||||
pr_err("XFAIL: this test is arm64-only\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void lkdtm_FORTIFY_OBJECT(void)
|
||||
{
|
||||
struct target {
|
||||
char a[10];
|
||||
} target[2] = {};
|
||||
int result;
|
||||
|
||||
/*
|
||||
* Using volatile prevents the compiler from determining the value of
|
||||
* 'size' at compile time. Without that, we would get a compile error
|
||||
* rather than a runtime error.
|
||||
*/
|
||||
volatile int size = 11;
|
||||
|
||||
pr_info("trying to read past the end of a struct\n");
|
||||
|
||||
result = memcmp(&target[0], &target[1], size);
|
||||
|
||||
/* Print result to prevent the code from being eliminated */
|
||||
pr_err("FAIL: fortify did not catch an object overread!\n"
|
||||
"\"%d\" was the memcmp result.\n", result);
|
||||
}
|
||||
|
||||
void lkdtm_FORTIFY_SUBOBJECT(void)
|
||||
{
|
||||
struct target {
|
||||
char a[10];
|
||||
char b[10];
|
||||
} target;
|
||||
char *src;
|
||||
|
||||
src = kmalloc(20, GFP_KERNEL);
|
||||
strscpy(src, "over ten bytes", 20);
|
||||
|
||||
pr_info("trying to strcpy past the end of a member of a struct\n");
|
||||
|
||||
/*
|
||||
* strncpy(target.a, src, 20); will hit a compile error because the
|
||||
* compiler knows at build time that target.a < 20 bytes. Use strcpy()
|
||||
* to force a runtime error.
|
||||
*/
|
||||
strcpy(target.a, src);
|
||||
|
||||
/* Use target.a to prevent the code from being eliminated */
|
||||
pr_err("FAIL: fortify did not catch an sub-object overrun!\n"
|
||||
"\"%s\" was copied.\n", target.a);
|
||||
|
||||
kfree(src);
|
||||
}
|
||||
|
@ -117,6 +117,8 @@ static const struct crashtype crashtypes[] = {
|
||||
CRASHTYPE(UNSET_SMEP),
|
||||
CRASHTYPE(CORRUPT_PAC),
|
||||
CRASHTYPE(UNALIGNED_LOAD_STORE_WRITE),
|
||||
CRASHTYPE(FORTIFY_OBJECT),
|
||||
CRASHTYPE(FORTIFY_SUBOBJECT),
|
||||
CRASHTYPE(OVERWRITE_ALLOCATION),
|
||||
CRASHTYPE(WRITE_AFTER_FREE),
|
||||
CRASHTYPE(READ_AFTER_FREE),
|
||||
@ -173,6 +175,7 @@ static const struct crashtype crashtypes[] = {
|
||||
CRASHTYPE(USERCOPY_KERNEL),
|
||||
CRASHTYPE(STACKLEAK_ERASING),
|
||||
CRASHTYPE(CFI_FORWARD_PROTO),
|
||||
CRASHTYPE(FORTIFIED_STRSCPY),
|
||||
#ifdef CONFIG_X86_32
|
||||
CRASHTYPE(DOUBLE_FAULT),
|
||||
#endif
|
||||
|
82
drivers/misc/lkdtm/fortify.c
Normal file
82
drivers/misc/lkdtm/fortify.c
Normal file
@ -0,0 +1,82 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2020 Francis Laniel <laniel_francis@privacyrequired.com>
|
||||
*
|
||||
* Add tests related to fortified functions in this file.
|
||||
*/
|
||||
#include "lkdtm.h"
|
||||
#include <linux/string.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
|
||||
/*
|
||||
* Calls fortified strscpy to test that it returns the same result as vanilla
|
||||
* strscpy and generate a panic because there is a write overflow (i.e. src
|
||||
* length is greater than dst length).
|
||||
*/
|
||||
void lkdtm_FORTIFIED_STRSCPY(void)
|
||||
{
|
||||
char *src;
|
||||
char dst[5];
|
||||
|
||||
struct {
|
||||
union {
|
||||
char big[10];
|
||||
char src[5];
|
||||
};
|
||||
} weird = { .big = "hello!" };
|
||||
char weird_dst[sizeof(weird.src) + 1];
|
||||
|
||||
src = kstrdup("foobar", GFP_KERNEL);
|
||||
|
||||
if (src == NULL)
|
||||
return;
|
||||
|
||||
/* Vanilla strscpy returns -E2BIG if size is 0. */
|
||||
if (strscpy(dst, src, 0) != -E2BIG)
|
||||
pr_warn("FAIL: strscpy() of 0 length did not return -E2BIG\n");
|
||||
|
||||
/* Vanilla strscpy returns -E2BIG if src is truncated. */
|
||||
if (strscpy(dst, src, sizeof(dst)) != -E2BIG)
|
||||
pr_warn("FAIL: strscpy() did not return -E2BIG while src is truncated\n");
|
||||
|
||||
/* After above call, dst must contain "foob" because src was truncated. */
|
||||
if (strncmp(dst, "foob", sizeof(dst)) != 0)
|
||||
pr_warn("FAIL: after strscpy() dst does not contain \"foob\" but \"%s\"\n",
|
||||
dst);
|
||||
|
||||
/* Shrink src so the strscpy() below succeeds. */
|
||||
src[3] = '\0';
|
||||
|
||||
/*
|
||||
* Vanilla strscpy returns number of character copied if everything goes
|
||||
* well.
|
||||
*/
|
||||
if (strscpy(dst, src, sizeof(dst)) != 3)
|
||||
pr_warn("FAIL: strscpy() did not return 3 while src was copied entirely truncated\n");
|
||||
|
||||
/* After above call, dst must contain "foo" because src was copied. */
|
||||
if (strncmp(dst, "foo", sizeof(dst)) != 0)
|
||||
pr_warn("FAIL: after strscpy() dst does not contain \"foo\" but \"%s\"\n",
|
||||
dst);
|
||||
|
||||
/* Test when src is embedded inside a union. */
|
||||
strscpy(weird_dst, weird.src, sizeof(weird_dst));
|
||||
|
||||
if (strcmp(weird_dst, "hello") != 0)
|
||||
pr_warn("FAIL: after strscpy() weird_dst does not contain \"hello\" but \"%s\"\n",
|
||||
weird_dst);
|
||||
|
||||
/* Restore src to its initial value. */
|
||||
src[3] = 'b';
|
||||
|
||||
/*
|
||||
* Use strlen here so size cannot be known at compile time and there is
|
||||
* a runtime write overflow.
|
||||
*/
|
||||
strscpy(dst, src, strlen(src));
|
||||
|
||||
pr_warn("FAIL: No overflow in above strscpy()\n");
|
||||
|
||||
kfree(src);
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
/* lkdtm_bugs.c */
|
||||
/* bugs.c */
|
||||
void __init lkdtm_bugs_init(int *recur_param);
|
||||
void lkdtm_PANIC(void);
|
||||
void lkdtm_BUG(void);
|
||||
@ -32,8 +32,10 @@ void lkdtm_STACK_GUARD_PAGE_TRAILING(void);
|
||||
void lkdtm_UNSET_SMEP(void);
|
||||
void lkdtm_DOUBLE_FAULT(void);
|
||||
void lkdtm_CORRUPT_PAC(void);
|
||||
void lkdtm_FORTIFY_OBJECT(void);
|
||||
void lkdtm_FORTIFY_SUBOBJECT(void);
|
||||
|
||||
/* lkdtm_heap.c */
|
||||
/* heap.c */
|
||||
void __init lkdtm_heap_init(void);
|
||||
void __exit lkdtm_heap_exit(void);
|
||||
void lkdtm_OVERWRITE_ALLOCATION(void);
|
||||
@ -45,7 +47,7 @@ void lkdtm_SLAB_FREE_DOUBLE(void);
|
||||
void lkdtm_SLAB_FREE_CROSS(void);
|
||||
void lkdtm_SLAB_FREE_PAGE(void);
|
||||
|
||||
/* lkdtm_perms.c */
|
||||
/* perms.c */
|
||||
void __init lkdtm_perms_init(void);
|
||||
void lkdtm_WRITE_RO(void);
|
||||
void lkdtm_WRITE_RO_AFTER_INIT(void);
|
||||
@ -60,7 +62,7 @@ void lkdtm_EXEC_NULL(void);
|
||||
void lkdtm_ACCESS_USERSPACE(void);
|
||||
void lkdtm_ACCESS_NULL(void);
|
||||
|
||||
/* lkdtm_refcount.c */
|
||||
/* refcount.c */
|
||||
void lkdtm_REFCOUNT_INC_OVERFLOW(void);
|
||||
void lkdtm_REFCOUNT_ADD_OVERFLOW(void);
|
||||
void lkdtm_REFCOUNT_INC_NOT_ZERO_OVERFLOW(void);
|
||||
@ -81,10 +83,10 @@ void lkdtm_REFCOUNT_SUB_AND_TEST_SATURATED(void);
|
||||
void lkdtm_REFCOUNT_TIMING(void);
|
||||
void lkdtm_ATOMIC_TIMING(void);
|
||||
|
||||
/* lkdtm_rodata.c */
|
||||
/* rodata.c */
|
||||
void lkdtm_rodata_do_nothing(void);
|
||||
|
||||
/* lkdtm_usercopy.c */
|
||||
/* usercopy.c */
|
||||
void __init lkdtm_usercopy_init(void);
|
||||
void __exit lkdtm_usercopy_exit(void);
|
||||
void lkdtm_USERCOPY_HEAP_SIZE_TO(void);
|
||||
@ -96,10 +98,13 @@ void lkdtm_USERCOPY_STACK_FRAME_FROM(void);
|
||||
void lkdtm_USERCOPY_STACK_BEYOND(void);
|
||||
void lkdtm_USERCOPY_KERNEL(void);
|
||||
|
||||
/* lkdtm_stackleak.c */
|
||||
/* stackleak.c */
|
||||
void lkdtm_STACKLEAK_ERASING(void);
|
||||
|
||||
/* cfi.c */
|
||||
void lkdtm_CFI_FORWARD_PROTO(void);
|
||||
|
||||
/* fortify.c */
|
||||
void lkdtm_FORTIFIED_STRSCPY(void);
|
||||
|
||||
#endif
|
||||
|
@ -497,7 +497,7 @@ static int remove_buf_file_handler(struct dentry *dentry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rchan_callbacks rfs_spec_scan_cb = {
|
||||
static const struct rchan_callbacks rfs_spec_scan_cb = {
|
||||
.create_buf_file = create_buf_file_handler,
|
||||
.remove_buf_file = remove_buf_file_handler,
|
||||
};
|
||||
|
@ -148,7 +148,7 @@ static int remove_buf_file_handler(struct dentry *dentry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rchan_callbacks rfs_scan_cb = {
|
||||
static const struct rchan_callbacks rfs_scan_cb = {
|
||||
.create_buf_file = create_buf_file_handler,
|
||||
.remove_buf_file = remove_buf_file_handler,
|
||||
};
|
||||
|
@ -1053,7 +1053,7 @@ static int remove_buf_file_handler(struct dentry *dentry)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct rchan_callbacks rfs_spec_scan_cb = {
|
||||
static const struct rchan_callbacks rfs_spec_scan_cb = {
|
||||
.create_buf_file = create_buf_file_handler,
|
||||
.remove_buf_file = remove_buf_file_handler,
|
||||
};
|
||||
|
@ -1412,71 +1412,6 @@ rio_mport_get_feature(struct rio_mport * port, int local, u16 destid,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rio_mport_get_feature);
|
||||
|
||||
/**
|
||||
* rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did
|
||||
* @vid: RIO vid to match or %RIO_ANY_ID to match all vids
|
||||
* @did: RIO did to match or %RIO_ANY_ID to match all dids
|
||||
* @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids
|
||||
* @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids
|
||||
* @from: Previous RIO device found in search, or %NULL for new search
|
||||
*
|
||||
* Iterates through the list of known RIO devices. If a RIO device is
|
||||
* found with a matching @vid, @did, @asm_vid, @asm_did, the reference
|
||||
* count to the device is incrememted and a pointer to its device
|
||||
* structure is returned. Otherwise, %NULL is returned. A new search
|
||||
* is initiated by passing %NULL to the @from argument. Otherwise, if
|
||||
* @from is not %NULL, searches continue from next device on the global
|
||||
* list. The reference count for @from is always decremented if it is
|
||||
* not %NULL.
|
||||
*/
|
||||
struct rio_dev *rio_get_asm(u16 vid, u16 did,
|
||||
u16 asm_vid, u16 asm_did, struct rio_dev *from)
|
||||
{
|
||||
struct list_head *n;
|
||||
struct rio_dev *rdev;
|
||||
|
||||
WARN_ON(in_interrupt());
|
||||
spin_lock(&rio_global_list_lock);
|
||||
n = from ? from->global_list.next : rio_devices.next;
|
||||
|
||||
while (n && (n != &rio_devices)) {
|
||||
rdev = rio_dev_g(n);
|
||||
if ((vid == RIO_ANY_ID || rdev->vid == vid) &&
|
||||
(did == RIO_ANY_ID || rdev->did == did) &&
|
||||
(asm_vid == RIO_ANY_ID || rdev->asm_vid == asm_vid) &&
|
||||
(asm_did == RIO_ANY_ID || rdev->asm_did == asm_did))
|
||||
goto exit;
|
||||
n = n->next;
|
||||
}
|
||||
rdev = NULL;
|
||||
exit:
|
||||
rio_dev_put(from);
|
||||
rdev = rio_dev_get(rdev);
|
||||
spin_unlock(&rio_global_list_lock);
|
||||
return rdev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rio_get_asm);
|
||||
|
||||
/**
|
||||
* rio_get_device - Begin or continue searching for a RIO device by vid/did
|
||||
* @vid: RIO vid to match or %RIO_ANY_ID to match all vids
|
||||
* @did: RIO did to match or %RIO_ANY_ID to match all dids
|
||||
* @from: Previous RIO device found in search, or %NULL for new search
|
||||
*
|
||||
* Iterates through the list of known RIO devices. If a RIO device is
|
||||
* found with a matching @vid and @did, the reference count to the
|
||||
* device is incrememted and a pointer to its device structure is returned.
|
||||
* Otherwise, %NULL is returned. A new search is initiated by passing %NULL
|
||||
* to the @from argument. Otherwise, if @from is not %NULL, searches
|
||||
* continue from next device on the global list. The reference count for
|
||||
* @from is always decremented if it is not %NULL.
|
||||
*/
|
||||
struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
|
||||
{
|
||||
return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rio_get_device);
|
||||
|
||||
/**
|
||||
* rio_std_route_add_entry - Add switch route table entry using standard
|
||||
* registers defined in RIO specification rev.1.3
|
||||
@ -2106,20 +2041,6 @@ found:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void rio_fixup_device(struct rio_dev *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static int rio_init(void)
|
||||
{
|
||||
struct rio_dev *dev = NULL;
|
||||
|
||||
while ((dev = rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) != NULL) {
|
||||
rio_fixup_device(dev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct workqueue_struct *rio_wq;
|
||||
|
||||
struct rio_disc_work {
|
||||
@ -2206,8 +2127,6 @@ int rio_init_mports(void)
|
||||
kfree(work);
|
||||
|
||||
no_disc:
|
||||
rio_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rio_init_mports);
|
||||
|
@ -350,7 +350,7 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent)
|
||||
|
||||
info->si_lasti = (le32_to_cpu(bfs_sb->s_start) - BFS_BSIZE) / sizeof(struct bfs_inode) + BFS_ROOT_INO - 1;
|
||||
if (info->si_lasti == BFS_MAX_LASTI)
|
||||
printf("WARNING: filesystem %s was created with 512 inodes, the real maximum is 511, mounting anyway\n", s->s_id);
|
||||
printf("NOTE: filesystem %s was created with 512 inodes, the real maximum is 511, mounting anyway\n", s->s_id);
|
||||
else if (info->si_lasti > BFS_MAX_LASTI) {
|
||||
printf("Impossible last inode number %lu > %d on %s\n", info->si_lasti, BFS_MAX_LASTI, s->s_id);
|
||||
goto out1;
|
||||
|
9
fs/dax.c
9
fs/dax.c
@ -810,12 +810,11 @@ static void dax_entry_mkclean(struct address_space *mapping, pgoff_t index,
|
||||
address = pgoff_address(index, vma);
|
||||
|
||||
/*
|
||||
* Note because we provide range to follow_pte_pmd it will
|
||||
* call mmu_notifier_invalidate_range_start() on our behalf
|
||||
* before taking any lock.
|
||||
* Note because we provide range to follow_pte it will call
|
||||
* mmu_notifier_invalidate_range_start() on our behalf before
|
||||
* taking any lock.
|
||||
*/
|
||||
if (follow_pte_pmd(vma->vm_mm, address, &range,
|
||||
&ptep, &pmdp, &ptl))
|
||||
if (follow_pte(vma->vm_mm, address, &range, &ptep, &pmdp, &ptl))
|
||||
continue;
|
||||
|
||||
/*
|
||||
|
@ -6,10 +6,15 @@
|
||||
*
|
||||
* NFSv4 callback procedures
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/nfs4.h>
|
||||
#include <linux/nfs_fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/rcupdate.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "nfs4_fs.h"
|
||||
#include "callback.h"
|
||||
#include "delegation.h"
|
||||
|
@ -134,14 +134,9 @@ static void nilfs_segctor_do_flush(struct nilfs_sc_info *, int);
|
||||
static void nilfs_segctor_do_immediate_flush(struct nilfs_sc_info *);
|
||||
static void nilfs_dispose_list(struct the_nilfs *, struct list_head *, int);
|
||||
|
||||
#define nilfs_cnt32_gt(a, b) \
|
||||
(typecheck(__u32, a) && typecheck(__u32, b) && \
|
||||
((__s32)(b) - (__s32)(a) < 0))
|
||||
#define nilfs_cnt32_ge(a, b) \
|
||||
(typecheck(__u32, a) && typecheck(__u32, b) && \
|
||||
((__s32)(a) - (__s32)(b) >= 0))
|
||||
#define nilfs_cnt32_lt(a, b) nilfs_cnt32_gt(b, a)
|
||||
#define nilfs_cnt32_le(a, b) nilfs_cnt32_ge(b, a)
|
||||
|
||||
static int nilfs_prepare_segment_lock(struct super_block *sb,
|
||||
struct nilfs_transaction_info *ti)
|
||||
|
@ -369,6 +369,34 @@ static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
|
||||
seq_puts(m, "vulnerable");
|
||||
break;
|
||||
}
|
||||
|
||||
seq_puts(m, "\nSpeculationIndirectBranch:\t");
|
||||
switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_INDIRECT_BRANCH)) {
|
||||
case -EINVAL:
|
||||
seq_puts(m, "unsupported");
|
||||
break;
|
||||
case PR_SPEC_NOT_AFFECTED:
|
||||
seq_puts(m, "not affected");
|
||||
break;
|
||||
case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE:
|
||||
seq_puts(m, "conditional force disabled");
|
||||
break;
|
||||
case PR_SPEC_PRCTL | PR_SPEC_DISABLE:
|
||||
seq_puts(m, "conditional disabled");
|
||||
break;
|
||||
case PR_SPEC_PRCTL | PR_SPEC_ENABLE:
|
||||
seq_puts(m, "conditional enabled");
|
||||
break;
|
||||
case PR_SPEC_ENABLE:
|
||||
seq_puts(m, "always enabled");
|
||||
break;
|
||||
case PR_SPEC_DISABLE:
|
||||
seq_puts(m, "always disabled");
|
||||
break;
|
||||
default:
|
||||
seq_puts(m, "unknown");
|
||||
break;
|
||||
}
|
||||
seq_putc(m, '\n');
|
||||
}
|
||||
|
||||
|
@ -2021,7 +2021,7 @@ const struct dentry_operations pid_dentry_operations =
|
||||
* file type from dcache entry.
|
||||
*
|
||||
* Since all of the proc inode numbers are dynamically generated, the inode
|
||||
* numbers do not exist until the inode is cache. This means creating the
|
||||
* numbers do not exist until the inode is cache. This means creating
|
||||
* the dcache entry in readdir is necessary to keep the inode numbers
|
||||
* reported by readdir in sync with the inode numbers reported
|
||||
* by stat.
|
||||
|
@ -349,6 +349,16 @@ static const struct file_operations proc_dir_operations = {
|
||||
.iterate_shared = proc_readdir,
|
||||
};
|
||||
|
||||
static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct dentry_operations proc_net_dentry_ops = {
|
||||
.d_revalidate = proc_net_d_revalidate,
|
||||
.d_delete = always_delete_dentry,
|
||||
};
|
||||
|
||||
/*
|
||||
* proc directories can do almost nothing..
|
||||
*/
|
||||
@ -471,8 +481,8 @@ struct proc_dir_entry *proc_symlink(const char *name,
|
||||
}
|
||||
EXPORT_SYMBOL(proc_symlink);
|
||||
|
||||
struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
|
||||
struct proc_dir_entry *parent, void *data)
|
||||
struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode,
|
||||
struct proc_dir_entry *parent, void *data, bool force_lookup)
|
||||
{
|
||||
struct proc_dir_entry *ent;
|
||||
|
||||
@ -484,10 +494,20 @@ struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
|
||||
ent->data = data;
|
||||
ent->proc_dir_ops = &proc_dir_operations;
|
||||
ent->proc_iops = &proc_dir_inode_operations;
|
||||
if (force_lookup) {
|
||||
pde_force_lookup(ent);
|
||||
}
|
||||
ent = proc_register(parent, ent);
|
||||
}
|
||||
return ent;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(_proc_mkdir);
|
||||
|
||||
struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
|
||||
struct proc_dir_entry *parent, void *data)
|
||||
{
|
||||
return _proc_mkdir(name, mode, parent, data, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_mkdir_data);
|
||||
|
||||
struct proc_dir_entry *proc_mkdir_mode(const char *name, umode_t mode,
|
||||
|
@ -190,10 +190,9 @@ struct dentry *proc_lookup_de(struct inode *, struct dentry *, struct proc_dir_e
|
||||
extern int proc_readdir(struct file *, struct dir_context *);
|
||||
int proc_readdir_de(struct file *, struct dir_context *, struct proc_dir_entry *);
|
||||
|
||||
static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)
|
||||
static inline void pde_get(struct proc_dir_entry *pde)
|
||||
{
|
||||
refcount_inc(&pde->refcnt);
|
||||
return pde;
|
||||
}
|
||||
extern void pde_put(struct proc_dir_entry *);
|
||||
|
||||
@ -310,3 +309,10 @@ extern unsigned long task_statm(struct mm_struct *,
|
||||
unsigned long *, unsigned long *,
|
||||
unsigned long *, unsigned long *);
|
||||
extern void task_mem(struct seq_file *, struct mm_struct *);
|
||||
|
||||
extern const struct dentry_operations proc_net_dentry_ops;
|
||||
static inline void pde_force_lookup(struct proc_dir_entry *pde)
|
||||
{
|
||||
/* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
|
||||
pde->proc_dops = &proc_net_dentry_ops;
|
||||
}
|
||||
|
@ -39,22 +39,6 @@ static struct net *get_proc_net(const struct inode *inode)
|
||||
return maybe_get_net(PDE_NET(PDE(inode)));
|
||||
}
|
||||
|
||||
static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dentry_operations proc_net_dentry_ops = {
|
||||
.d_revalidate = proc_net_d_revalidate,
|
||||
.d_delete = always_delete_dentry,
|
||||
};
|
||||
|
||||
static void pde_force_lookup(struct proc_dir_entry *pde)
|
||||
{
|
||||
/* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
|
||||
pde->proc_dops = &proc_net_dentry_ops;
|
||||
}
|
||||
|
||||
static int seq_open_net(struct inode *inode, struct file *file)
|
||||
{
|
||||
unsigned int state_size = PDE(inode)->state_size;
|
||||
@ -140,7 +124,7 @@ EXPORT_SYMBOL_GPL(proc_create_net_data);
|
||||
* @mode: The file's access mode.
|
||||
* @parent: The parent directory in which to create.
|
||||
* @ops: The seq_file ops with which to read the file.
|
||||
* @write: The write method which which to 'modify' the file.
|
||||
* @write: The write method with which to 'modify' the file.
|
||||
* @data: Data for retrieval by PDE_DATA().
|
||||
*
|
||||
* Create a network namespaced proc file in the @parent directory with the
|
||||
@ -232,7 +216,7 @@ EXPORT_SYMBOL_GPL(proc_create_net_single);
|
||||
* @mode: The file's access mode.
|
||||
* @parent: The parent directory in which to create.
|
||||
* @show: The seqfile show method with which to read the file.
|
||||
* @write: The write method which which to 'modify' the file.
|
||||
* @write: The write method with which to 'modify' the file.
|
||||
* @data: Data for retrieval by PDE_DATA().
|
||||
*
|
||||
* Create a network-namespaced proc file in the @parent directory with the
|
||||
|
@ -26,7 +26,7 @@
|
||||
*
|
||||
* The result is undefined if the size is 0.
|
||||
*/
|
||||
static inline __attribute_const__ int get_order(unsigned long size)
|
||||
static __always_inline __attribute_const__ int get_order(unsigned long size)
|
||||
{
|
||||
if (__builtin_constant_p(size)) {
|
||||
if (!size)
|
||||
|
@ -126,8 +126,6 @@ extern void bitmap_free(const unsigned long *bitmap);
|
||||
* lib/bitmap.c provides these functions:
|
||||
*/
|
||||
|
||||
extern int __bitmap_empty(const unsigned long *bitmap, unsigned int nbits);
|
||||
extern int __bitmap_full(const unsigned long *bitmap, unsigned int nbits);
|
||||
extern int __bitmap_equal(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, unsigned int nbits);
|
||||
extern bool __pure __bitmap_or_equal(const unsigned long *src1,
|
||||
@ -379,7 +377,7 @@ static inline int bitmap_subset(const unsigned long *src1,
|
||||
return __bitmap_subset(src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline int bitmap_empty(const unsigned long *src, unsigned nbits)
|
||||
static inline bool bitmap_empty(const unsigned long *src, unsigned nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
|
||||
@ -387,7 +385,7 @@ static inline int bitmap_empty(const unsigned long *src, unsigned nbits)
|
||||
return find_first_bit(src, nbits) == nbits;
|
||||
}
|
||||
|
||||
static inline int bitmap_full(const unsigned long *src, unsigned int nbits)
|
||||
static inline bool bitmap_full(const unsigned long *src, unsigned int nbits)
|
||||
{
|
||||
if (small_const_nbits(nbits))
|
||||
return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
|
@ -1,9 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_BITOPS_H
|
||||
#define _LINUX_BITOPS_H
|
||||
|
||||
#include <asm/types.h>
|
||||
#include <linux/bits.h>
|
||||
|
||||
#include <uapi/linux/kernel.h>
|
||||
|
||||
/* Set bits in the first 'n' bytes when loaded from memory */
|
||||
#ifdef __LITTLE_ENDIAN
|
||||
# define aligned_byte_mask(n) ((1UL << 8*(n))-1)
|
||||
@ -12,10 +15,10 @@
|
||||
#endif
|
||||
|
||||
#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
|
||||
#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
|
||||
#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
|
||||
#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
|
||||
#define BITS_TO_LONGS(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(long))
|
||||
#define BITS_TO_U64(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u64))
|
||||
#define BITS_TO_U32(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(u32))
|
||||
#define BITS_TO_BYTES(nr) __KERNEL_DIV_ROUND_UP(nr, BITS_PER_TYPE(char))
|
||||
|
||||
extern unsigned int __sw_hweight8(unsigned int w);
|
||||
extern unsigned int __sw_hweight16(unsigned int w);
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/rculist.h>
|
||||
#include <linux/rculist_bl.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
@ -3,7 +3,9 @@
|
||||
#define _LINUX_IOMMU_HELPER_H
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
static inline unsigned long iommu_device_max_index(unsigned long size,
|
||||
unsigned long offset,
|
||||
|
@ -2,7 +2,6 @@
|
||||
#ifndef _LINUX_KERNEL_H
|
||||
#define _LINUX_KERNEL_H
|
||||
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/linkage.h>
|
||||
@ -11,12 +10,14 @@
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/typecheck.h>
|
||||
#include <linux/printk.h>
|
||||
#include <linux/build_bug.h>
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/div64.h>
|
||||
|
||||
#include <uapi/linux/kernel.h>
|
||||
|
||||
#define STACK_MAGIC 0xdeadbeef
|
||||
@ -54,125 +55,11 @@
|
||||
} \
|
||||
)
|
||||
|
||||
/*
|
||||
* This looks more complex than it should be. But we need to
|
||||
* get the type for the ~ right in round_down (it needs to be
|
||||
* as wide as the result!), and we want to evaluate the macro
|
||||
* arguments just once each.
|
||||
*/
|
||||
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
|
||||
/**
|
||||
* round_up - round up to next specified power of 2
|
||||
* @x: the value to round
|
||||
* @y: multiple to round up to (must be a power of 2)
|
||||
*
|
||||
* Rounds @x up to next multiple of @y (which must be a power of 2).
|
||||
* To perform arbitrary rounding up, use roundup() below.
|
||||
*/
|
||||
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
|
||||
/**
|
||||
* round_down - round down to next specified power of 2
|
||||
* @x: the value to round
|
||||
* @y: multiple to round down to (must be a power of 2)
|
||||
*
|
||||
* Rounds @x down to next multiple of @y (which must be a power of 2).
|
||||
* To perform arbitrary rounding down, use rounddown() below.
|
||||
*/
|
||||
#define round_down(x, y) ((x) & ~__round_mask(x, y))
|
||||
|
||||
#define typeof_member(T, m) typeof(((T*)0)->m)
|
||||
|
||||
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
|
||||
|
||||
#define DIV_ROUND_DOWN_ULL(ll, d) \
|
||||
({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
|
||||
|
||||
#define DIV_ROUND_UP_ULL(ll, d) \
|
||||
DIV_ROUND_DOWN_ULL((unsigned long long)(ll) + (d) - 1, (d))
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP_ULL(ll, d)
|
||||
#else
|
||||
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP(ll,d)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* roundup - round up to the next specified multiple
|
||||
* @x: the value to up
|
||||
* @y: multiple to round up to
|
||||
*
|
||||
* Rounds @x up to next multiple of @y. If @y will always be a power
|
||||
* of 2, consider using the faster round_up().
|
||||
*/
|
||||
#define roundup(x, y) ( \
|
||||
{ \
|
||||
typeof(y) __y = y; \
|
||||
(((x) + (__y - 1)) / __y) * __y; \
|
||||
} \
|
||||
)
|
||||
/**
|
||||
* rounddown - round down to next specified multiple
|
||||
* @x: the value to round
|
||||
* @y: multiple to round down to
|
||||
*
|
||||
* Rounds @x down to next multiple of @y. If @y will always be a power
|
||||
* of 2, consider using the faster round_down().
|
||||
*/
|
||||
#define rounddown(x, y) ( \
|
||||
{ \
|
||||
typeof(x) __x = (x); \
|
||||
__x - (__x % (y)); \
|
||||
} \
|
||||
)
|
||||
|
||||
/*
|
||||
* Divide positive or negative dividend by positive or negative divisor
|
||||
* and round to closest integer. Result is undefined for negative
|
||||
* divisors if the dividend variable type is unsigned and for negative
|
||||
* dividends if the divisor variable type is unsigned.
|
||||
*/
|
||||
#define DIV_ROUND_CLOSEST(x, divisor)( \
|
||||
{ \
|
||||
typeof(x) __x = x; \
|
||||
typeof(divisor) __d = divisor; \
|
||||
(((typeof(x))-1) > 0 || \
|
||||
((typeof(divisor))-1) > 0 || \
|
||||
(((__x) > 0) == ((__d) > 0))) ? \
|
||||
(((__x) + ((__d) / 2)) / (__d)) : \
|
||||
(((__x) - ((__d) / 2)) / (__d)); \
|
||||
} \
|
||||
)
|
||||
/*
|
||||
* Same as above but for u64 dividends. divisor must be a 32-bit
|
||||
* number.
|
||||
*/
|
||||
#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \
|
||||
{ \
|
||||
typeof(divisor) __d = divisor; \
|
||||
unsigned long long _tmp = (x) + (__d) / 2; \
|
||||
do_div(_tmp, __d); \
|
||||
_tmp; \
|
||||
} \
|
||||
)
|
||||
|
||||
/*
|
||||
* Multiplies an integer by a fraction, while avoiding unnecessary
|
||||
* overflow or loss of precision.
|
||||
*/
|
||||
#define mult_frac(x, numer, denom)( \
|
||||
{ \
|
||||
typeof(x) quot = (x) / (denom); \
|
||||
typeof(x) rem = (x) % (denom); \
|
||||
(quot * (numer)) + ((rem * (numer)) / (denom)); \
|
||||
} \
|
||||
)
|
||||
|
||||
|
||||
#define _RET_IP_ (unsigned long)__builtin_return_address(0)
|
||||
#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; })
|
||||
|
||||
#define sector_div(a, b) do_div(a, b)
|
||||
|
||||
/**
|
||||
* upper_32_bits - return bits 32-63 of a number
|
||||
* @n: the number we're accessing
|
||||
@ -272,48 +159,6 @@ extern void __cant_migrate(const char *file, int line);
|
||||
|
||||
#define might_sleep_if(cond) do { if (cond) might_sleep(); } while (0)
|
||||
|
||||
/**
|
||||
* abs - return absolute value of an argument
|
||||
* @x: the value. If it is unsigned type, it is converted to signed type first.
|
||||
* char is treated as if it was signed (regardless of whether it really is)
|
||||
* but the macro's return type is preserved as char.
|
||||
*
|
||||
* Return: an absolute value of x.
|
||||
*/
|
||||
#define abs(x) __abs_choose_expr(x, long long, \
|
||||
__abs_choose_expr(x, long, \
|
||||
__abs_choose_expr(x, int, \
|
||||
__abs_choose_expr(x, short, \
|
||||
__abs_choose_expr(x, char, \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(x), char), \
|
||||
(char)({ signed char __x = (x); __x<0?-__x:__x; }), \
|
||||
((void)0)))))))
|
||||
|
||||
#define __abs_choose_expr(x, type, other) __builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(x), signed type) || \
|
||||
__builtin_types_compatible_p(typeof(x), unsigned type), \
|
||||
({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)
|
||||
|
||||
/**
|
||||
* reciprocal_scale - "scale" a value into range [0, ep_ro)
|
||||
* @val: value
|
||||
* @ep_ro: right open interval endpoint
|
||||
*
|
||||
* Perform a "reciprocal multiplication" in order to "scale" a value into
|
||||
* range [0, @ep_ro), where the upper interval endpoint is right-open.
|
||||
* This is useful, e.g. for accessing a index of an array containing
|
||||
* @ep_ro elements, for example. Think of it as sort of modulus, only that
|
||||
* the result isn't that of modulo. ;) Note that if initial input is a
|
||||
* small value, then result will return 0.
|
||||
*
|
||||
* Return: a result based on @val in interval [0, @ep_ro).
|
||||
*/
|
||||
static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
|
||||
{
|
||||
return (u32)(((u64) val * ep_ro) >> 32);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_MMU) && \
|
||||
(defined(CONFIG_PROVE_LOCKING) || defined(CONFIG_DEBUG_ATOMIC_SLEEP))
|
||||
#define might_fault() __might_fault(__FILE__, __LINE__)
|
||||
@ -515,18 +360,6 @@ extern int __kernel_text_address(unsigned long addr);
|
||||
extern int kernel_text_address(unsigned long addr);
|
||||
extern int func_ptr_is_kernel_text(void *ptr);
|
||||
|
||||
u64 int_pow(u64 base, unsigned int exp);
|
||||
unsigned long int_sqrt(unsigned long);
|
||||
|
||||
#if BITS_PER_LONG < 64
|
||||
u32 int_sqrt64(u64 x);
|
||||
#else
|
||||
static inline u32 int_sqrt64(u64 x)
|
||||
{
|
||||
return (u32)int_sqrt(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
extern unsigned int sysctl_oops_all_cpu_backtrace;
|
||||
#else
|
||||
|
@ -156,7 +156,8 @@ unsigned long __rounddown_pow_of_two(unsigned long n)
|
||||
#define ilog2(n) \
|
||||
( \
|
||||
__builtin_constant_p(n) ? \
|
||||
const_ilog2(n) : \
|
||||
((n) < 2 ? 0 : \
|
||||
63 - __builtin_clzll(n)) : \
|
||||
(sizeof(n) <= 4) ? \
|
||||
__ilog2_u32(n) : \
|
||||
__ilog2_u64(n) \
|
||||
|
177
include/linux/math.h
Normal file
177
include/linux/math.h
Normal file
@ -0,0 +1,177 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _LINUX_MATH_H
|
||||
#define _LINUX_MATH_H
|
||||
|
||||
#include <asm/div64.h>
|
||||
#include <uapi/linux/kernel.h>
|
||||
|
||||
/*
|
||||
* This looks more complex than it should be. But we need to
|
||||
* get the type for the ~ right in round_down (it needs to be
|
||||
* as wide as the result!), and we want to evaluate the macro
|
||||
* arguments just once each.
|
||||
*/
|
||||
#define __round_mask(x, y) ((__typeof__(x))((y)-1))
|
||||
|
||||
/**
|
||||
* round_up - round up to next specified power of 2
|
||||
* @x: the value to round
|
||||
* @y: multiple to round up to (must be a power of 2)
|
||||
*
|
||||
* Rounds @x up to next multiple of @y (which must be a power of 2).
|
||||
* To perform arbitrary rounding up, use roundup() below.
|
||||
*/
|
||||
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
|
||||
|
||||
/**
|
||||
* round_down - round down to next specified power of 2
|
||||
* @x: the value to round
|
||||
* @y: multiple to round down to (must be a power of 2)
|
||||
*
|
||||
* Rounds @x down to next multiple of @y (which must be a power of 2).
|
||||
* To perform arbitrary rounding down, use rounddown() below.
|
||||
*/
|
||||
#define round_down(x, y) ((x) & ~__round_mask(x, y))
|
||||
|
||||
#define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
|
||||
|
||||
#define DIV_ROUND_DOWN_ULL(ll, d) \
|
||||
({ unsigned long long _tmp = (ll); do_div(_tmp, d); _tmp; })
|
||||
|
||||
#define DIV_ROUND_UP_ULL(ll, d) \
|
||||
DIV_ROUND_DOWN_ULL((unsigned long long)(ll) + (d) - 1, (d))
|
||||
|
||||
#if BITS_PER_LONG == 32
|
||||
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP_ULL(ll, d)
|
||||
#else
|
||||
# define DIV_ROUND_UP_SECTOR_T(ll,d) DIV_ROUND_UP(ll,d)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* roundup - round up to the next specified multiple
|
||||
* @x: the value to up
|
||||
* @y: multiple to round up to
|
||||
*
|
||||
* Rounds @x up to next multiple of @y. If @y will always be a power
|
||||
* of 2, consider using the faster round_up().
|
||||
*/
|
||||
#define roundup(x, y) ( \
|
||||
{ \
|
||||
typeof(y) __y = y; \
|
||||
(((x) + (__y - 1)) / __y) * __y; \
|
||||
} \
|
||||
)
|
||||
/**
|
||||
* rounddown - round down to next specified multiple
|
||||
* @x: the value to round
|
||||
* @y: multiple to round down to
|
||||
*
|
||||
* Rounds @x down to next multiple of @y. If @y will always be a power
|
||||
* of 2, consider using the faster round_down().
|
||||
*/
|
||||
#define rounddown(x, y) ( \
|
||||
{ \
|
||||
typeof(x) __x = (x); \
|
||||
__x - (__x % (y)); \
|
||||
} \
|
||||
)
|
||||
|
||||
/*
|
||||
* Divide positive or negative dividend by positive or negative divisor
|
||||
* and round to closest integer. Result is undefined for negative
|
||||
* divisors if the dividend variable type is unsigned and for negative
|
||||
* dividends if the divisor variable type is unsigned.
|
||||
*/
|
||||
#define DIV_ROUND_CLOSEST(x, divisor)( \
|
||||
{ \
|
||||
typeof(x) __x = x; \
|
||||
typeof(divisor) __d = divisor; \
|
||||
(((typeof(x))-1) > 0 || \
|
||||
((typeof(divisor))-1) > 0 || \
|
||||
(((__x) > 0) == ((__d) > 0))) ? \
|
||||
(((__x) + ((__d) / 2)) / (__d)) : \
|
||||
(((__x) - ((__d) / 2)) / (__d)); \
|
||||
} \
|
||||
)
|
||||
/*
|
||||
* Same as above but for u64 dividends. divisor must be a 32-bit
|
||||
* number.
|
||||
*/
|
||||
#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \
|
||||
{ \
|
||||
typeof(divisor) __d = divisor; \
|
||||
unsigned long long _tmp = (x) + (__d) / 2; \
|
||||
do_div(_tmp, __d); \
|
||||
_tmp; \
|
||||
} \
|
||||
)
|
||||
|
||||
/*
|
||||
* Multiplies an integer by a fraction, while avoiding unnecessary
|
||||
* overflow or loss of precision.
|
||||
*/
|
||||
#define mult_frac(x, numer, denom)( \
|
||||
{ \
|
||||
typeof(x) quot = (x) / (denom); \
|
||||
typeof(x) rem = (x) % (denom); \
|
||||
(quot * (numer)) + ((rem * (numer)) / (denom)); \
|
||||
} \
|
||||
)
|
||||
|
||||
#define sector_div(a, b) do_div(a, b)
|
||||
|
||||
/**
|
||||
* abs - return absolute value of an argument
|
||||
* @x: the value. If it is unsigned type, it is converted to signed type first.
|
||||
* char is treated as if it was signed (regardless of whether it really is)
|
||||
* but the macro's return type is preserved as char.
|
||||
*
|
||||
* Return: an absolute value of x.
|
||||
*/
|
||||
#define abs(x) __abs_choose_expr(x, long long, \
|
||||
__abs_choose_expr(x, long, \
|
||||
__abs_choose_expr(x, int, \
|
||||
__abs_choose_expr(x, short, \
|
||||
__abs_choose_expr(x, char, \
|
||||
__builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(x), char), \
|
||||
(char)({ signed char __x = (x); __x<0?-__x:__x; }), \
|
||||
((void)0)))))))
|
||||
|
||||
#define __abs_choose_expr(x, type, other) __builtin_choose_expr( \
|
||||
__builtin_types_compatible_p(typeof(x), signed type) || \
|
||||
__builtin_types_compatible_p(typeof(x), unsigned type), \
|
||||
({ signed type __x = (x); __x < 0 ? -__x : __x; }), other)
|
||||
|
||||
/**
|
||||
* reciprocal_scale - "scale" a value into range [0, ep_ro)
|
||||
* @val: value
|
||||
* @ep_ro: right open interval endpoint
|
||||
*
|
||||
* Perform a "reciprocal multiplication" in order to "scale" a value into
|
||||
* range [0, @ep_ro), where the upper interval endpoint is right-open.
|
||||
* This is useful, e.g. for accessing a index of an array containing
|
||||
* @ep_ro elements, for example. Think of it as sort of modulus, only that
|
||||
* the result isn't that of modulo. ;) Note that if initial input is a
|
||||
* small value, then result will return 0.
|
||||
*
|
||||
* Return: a result based on @val in interval [0, @ep_ro).
|
||||
*/
|
||||
static inline u32 reciprocal_scale(u32 val, u32 ep_ro)
|
||||
{
|
||||
return (u32)(((u64) val * ep_ro) >> 32);
|
||||
}
|
||||
|
||||
u64 int_pow(u64 base, unsigned int exp);
|
||||
unsigned long int_sqrt(unsigned long);
|
||||
|
||||
#if BITS_PER_LONG < 64
|
||||
u32 int_sqrt64(u64 x);
|
||||
#else
|
||||
static inline u32 int_sqrt64(u64 x)
|
||||
{
|
||||
return (u32)int_sqrt(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _LINUX_MATH_H */
|
@ -1641,9 +1641,9 @@ void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
|
||||
unsigned long end, unsigned long floor, unsigned long ceiling);
|
||||
int
|
||||
copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma);
|
||||
int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
|
||||
struct mmu_notifier_range *range,
|
||||
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
|
||||
int follow_pte(struct mm_struct *mm, unsigned long address,
|
||||
struct mmu_notifier_range *range, pte_t **ptepp, pmd_t **pmdpp,
|
||||
spinlock_t **ptlp);
|
||||
int follow_pfn(struct vm_area_struct *vma, unsigned long address,
|
||||
unsigned long *pfn);
|
||||
int follow_phys(struct vm_area_struct *vma, unsigned long address,
|
||||
|
@ -80,6 +80,7 @@ extern void proc_flush_pid(struct pid *);
|
||||
|
||||
extern struct proc_dir_entry *proc_symlink(const char *,
|
||||
struct proc_dir_entry *, const char *);
|
||||
struct proc_dir_entry *_proc_mkdir(const char *, umode_t, struct proc_dir_entry *, void *, bool);
|
||||
extern struct proc_dir_entry *proc_mkdir(const char *, struct proc_dir_entry *);
|
||||
extern struct proc_dir_entry *proc_mkdir_data(const char *, umode_t,
|
||||
struct proc_dir_entry *, void *);
|
||||
@ -162,6 +163,11 @@ static inline struct proc_dir_entry *proc_symlink(const char *name,
|
||||
static inline struct proc_dir_entry *proc_mkdir(const char *name,
|
||||
struct proc_dir_entry *parent) {return NULL;}
|
||||
static inline struct proc_dir_entry *proc_create_mount_point(const char *name) { return NULL; }
|
||||
static inline struct proc_dir_entry *_proc_mkdir(const char *name, umode_t mode,
|
||||
struct proc_dir_entry *parent, void *data, bool force_lookup)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline struct proc_dir_entry *proc_mkdir_data(const char *name,
|
||||
umode_t mode, struct proc_dir_entry *parent, void *data) { return NULL; }
|
||||
static inline struct proc_dir_entry *proc_mkdir_mode(const char *name,
|
||||
@ -199,7 +205,7 @@ struct net;
|
||||
static inline struct proc_dir_entry *proc_net_mkdir(
|
||||
struct net *net, const char *name, struct proc_dir_entry *parent)
|
||||
{
|
||||
return proc_mkdir_data(name, 0, parent, net);
|
||||
return _proc_mkdir(name, 0, parent, net, true);
|
||||
}
|
||||
|
||||
struct ns_common;
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef __LINUX_RCU_NODE_TREE_H
|
||||
#define __LINUX_RCU_NODE_TREE_H
|
||||
|
||||
#include <linux/math.h>
|
||||
|
||||
/*
|
||||
* Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and
|
||||
* CONFIG_RCU_FANOUT_LEAF.
|
||||
|
@ -62,7 +62,7 @@ struct rchan
|
||||
size_t subbuf_size; /* sub-buffer size */
|
||||
size_t n_subbufs; /* number of sub-buffers per buffer */
|
||||
size_t alloc_size; /* total buffer size allocated */
|
||||
struct rchan_callbacks *cb; /* client callbacks */
|
||||
const struct rchan_callbacks *cb; /* client callbacks */
|
||||
struct kref kref; /* channel refcount */
|
||||
void *private_data; /* for user-defined data */
|
||||
size_t last_toobig; /* tried to log event > subbuf size */
|
||||
@ -89,6 +89,8 @@ struct rchan_callbacks
|
||||
* The client should return 1 to continue logging, 0 to stop
|
||||
* logging.
|
||||
*
|
||||
* This callback is optional.
|
||||
*
|
||||
* NOTE: subbuf_start will also be invoked when the buffer is
|
||||
* created, so that the first sub-buffer can be initialized
|
||||
* if necessary. In this case, prev_subbuf will be NULL.
|
||||
@ -101,25 +103,6 @@ struct rchan_callbacks
|
||||
void *prev_subbuf,
|
||||
size_t prev_padding);
|
||||
|
||||
/*
|
||||
* buf_mapped - relay buffer mmap notification
|
||||
* @buf: the channel buffer
|
||||
* @filp: relay file pointer
|
||||
*
|
||||
* Called when a relay file is successfully mmapped
|
||||
*/
|
||||
void (*buf_mapped)(struct rchan_buf *buf,
|
||||
struct file *filp);
|
||||
|
||||
/*
|
||||
* buf_unmapped - relay buffer unmap notification
|
||||
* @buf: the channel buffer
|
||||
* @filp: relay file pointer
|
||||
*
|
||||
* Called when a relay file is successfully unmapped
|
||||
*/
|
||||
void (*buf_unmapped)(struct rchan_buf *buf,
|
||||
struct file *filp);
|
||||
/*
|
||||
* create_buf_file - create file to represent a relay channel buffer
|
||||
* @filename: the name of the file to create
|
||||
@ -141,6 +124,8 @@ struct rchan_callbacks
|
||||
* cause relay_open() to create a single global buffer rather
|
||||
* than the default set of per-cpu buffers.
|
||||
*
|
||||
* This callback is mandatory.
|
||||
*
|
||||
* See Documentation/filesystems/relay.rst for more info.
|
||||
*/
|
||||
struct dentry *(*create_buf_file)(const char *filename,
|
||||
@ -158,6 +143,8 @@ struct rchan_callbacks
|
||||
* channel buffer.
|
||||
*
|
||||
* The callback should return 0 if successful, negative if not.
|
||||
*
|
||||
* This callback is mandatory.
|
||||
*/
|
||||
int (*remove_buf_file)(struct dentry *dentry);
|
||||
};
|
||||
@ -170,7 +157,7 @@ struct rchan *relay_open(const char *base_filename,
|
||||
struct dentry *parent,
|
||||
size_t subbuf_size,
|
||||
size_t n_subbufs,
|
||||
struct rchan_callbacks *cb,
|
||||
const struct rchan_callbacks *cb,
|
||||
void *private_data);
|
||||
extern int relay_late_setup_files(struct rchan *chan,
|
||||
const char *base_filename,
|
||||
|
@ -444,9 +444,6 @@ static inline void rio_set_drvdata(struct rio_dev *rdev, void *data)
|
||||
/* Misc driver helpers */
|
||||
extern u16 rio_local_get_device_id(struct rio_mport *port);
|
||||
extern void rio_local_set_device_id(struct rio_mport *port, u16 did);
|
||||
extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from);
|
||||
extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did,
|
||||
struct rio_dev *from);
|
||||
extern int rio_init_mports(void);
|
||||
|
||||
#endif /* LINUX_RIO_DRV_H */
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <linux/compiler.h> /* for inline */
|
||||
#include <linux/types.h> /* for size_t */
|
||||
#include <linux/stddef.h> /* for NULL */
|
||||
#include <linux/errno.h> /* for E2BIG */
|
||||
#include <stdarg.h>
|
||||
#include <uapi/linux/string.h>
|
||||
|
||||
@ -292,7 +293,7 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size)
|
||||
|
||||
__FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
|
||||
{
|
||||
size_t p_size = __builtin_object_size(p, 0);
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
if (__builtin_constant_p(size) && p_size < size)
|
||||
__write_overflow();
|
||||
if (p_size < size)
|
||||
@ -302,7 +303,7 @@ __FORTIFY_INLINE char *strncpy(char *p, const char *q, __kernel_size_t size)
|
||||
|
||||
__FORTIFY_INLINE char *strcat(char *p, const char *q)
|
||||
{
|
||||
size_t p_size = __builtin_object_size(p, 0);
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
if (p_size == (size_t)-1)
|
||||
return __underlying_strcat(p, q);
|
||||
if (strlcat(p, q, p_size) >= p_size)
|
||||
@ -313,7 +314,7 @@ __FORTIFY_INLINE char *strcat(char *p, const char *q)
|
||||
__FORTIFY_INLINE __kernel_size_t strlen(const char *p)
|
||||
{
|
||||
__kernel_size_t ret;
|
||||
size_t p_size = __builtin_object_size(p, 0);
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
|
||||
/* Work around gcc excess stack consumption issue */
|
||||
if (p_size == (size_t)-1 ||
|
||||
@ -328,7 +329,7 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
|
||||
extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(strnlen);
|
||||
__FORTIFY_INLINE __kernel_size_t strnlen(const char *p, __kernel_size_t maxlen)
|
||||
{
|
||||
size_t p_size = __builtin_object_size(p, 0);
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
__kernel_size_t ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
|
||||
if (p_size <= ret && maxlen != ret)
|
||||
fortify_panic(__func__);
|
||||
@ -340,8 +341,8 @@ extern size_t __real_strlcpy(char *, const char *, size_t) __RENAME(strlcpy);
|
||||
__FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
|
||||
{
|
||||
size_t ret;
|
||||
size_t p_size = __builtin_object_size(p, 0);
|
||||
size_t q_size = __builtin_object_size(q, 0);
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
size_t q_size = __builtin_object_size(q, 1);
|
||||
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
||||
return __real_strlcpy(p, q, size);
|
||||
ret = strlen(q);
|
||||
@ -357,12 +358,59 @@ __FORTIFY_INLINE size_t strlcpy(char *p, const char *q, size_t size)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* defined after fortified strnlen to reuse it */
|
||||
extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);
|
||||
__FORTIFY_INLINE ssize_t strscpy(char *p, const char *q, size_t size)
|
||||
{
|
||||
size_t len;
|
||||
/* Use string size rather than possible enclosing struct size. */
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
size_t q_size = __builtin_object_size(q, 1);
|
||||
|
||||
/* If we cannot get size of p and q default to call strscpy. */
|
||||
if (p_size == (size_t) -1 && q_size == (size_t) -1)
|
||||
return __real_strscpy(p, q, size);
|
||||
|
||||
/*
|
||||
* If size can be known at compile time and is greater than
|
||||
* p_size, generate a compile time write overflow error.
|
||||
*/
|
||||
if (__builtin_constant_p(size) && size > p_size)
|
||||
__write_overflow();
|
||||
|
||||
/*
|
||||
* This call protects from read overflow, because len will default to q
|
||||
* length if it smaller than size.
|
||||
*/
|
||||
len = strnlen(q, size);
|
||||
/*
|
||||
* If len equals size, we will copy only size bytes which leads to
|
||||
* -E2BIG being returned.
|
||||
* Otherwise we will copy len + 1 because of the final '\O'.
|
||||
*/
|
||||
len = len == size ? size : len + 1;
|
||||
|
||||
/*
|
||||
* Generate a runtime write overflow error if len is greater than
|
||||
* p_size.
|
||||
*/
|
||||
if (len > p_size)
|
||||
fortify_panic(__func__);
|
||||
|
||||
/*
|
||||
* We can now safely call vanilla strscpy because we are protected from:
|
||||
* 1. Read overflow thanks to call to strnlen().
|
||||
* 2. Write overflow thanks to above ifs.
|
||||
*/
|
||||
return __real_strscpy(p, q, len);
|
||||
}
|
||||
|
||||
/* defined after fortified strlen and strnlen to reuse them */
|
||||
__FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
|
||||
{
|
||||
size_t p_len, copy_len;
|
||||
size_t p_size = __builtin_object_size(p, 0);
|
||||
size_t q_size = __builtin_object_size(q, 0);
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
size_t q_size = __builtin_object_size(q, 1);
|
||||
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
||||
return __underlying_strncat(p, q, count);
|
||||
p_len = strlen(p);
|
||||
@ -475,11 +523,16 @@ __FORTIFY_INLINE void *kmemdup(const void *p, size_t size, gfp_t gfp)
|
||||
/* defined after fortified strlen and memcpy to reuse them */
|
||||
__FORTIFY_INLINE char *strcpy(char *p, const char *q)
|
||||
{
|
||||
size_t p_size = __builtin_object_size(p, 0);
|
||||
size_t q_size = __builtin_object_size(q, 0);
|
||||
size_t p_size = __builtin_object_size(p, 1);
|
||||
size_t q_size = __builtin_object_size(q, 1);
|
||||
size_t size;
|
||||
if (p_size == (size_t)-1 && q_size == (size_t)-1)
|
||||
return __underlying_strcpy(p, q);
|
||||
memcpy(p, q, strlen(q) + 1);
|
||||
size = strlen(q) + 1;
|
||||
/* test here to use the more stringent object size */
|
||||
if (p_size < size)
|
||||
fortify_panic(__func__);
|
||||
memcpy(p, q, size);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
#ifndef _LINUX_UNITS_H
|
||||
#define _LINUX_UNITS_H
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
|
||||
#define ABSOLUTE_ZERO_MILLICELSIUS -273150
|
||||
|
||||
|
@ -34,8 +34,11 @@ KCOV_INSTRUMENT_extable.o := n
|
||||
KCOV_INSTRUMENT_stacktrace.o := n
|
||||
# Don't self-instrument.
|
||||
KCOV_INSTRUMENT_kcov.o := n
|
||||
# If sanitizers detect any issues in kcov, it may lead to recursion
|
||||
# via printk, etc.
|
||||
KASAN_SANITIZE_kcov.o := n
|
||||
KCSAN_SANITIZE_kcov.o := n
|
||||
UBSAN_SANITIZE_kcov.o := n
|
||||
CFLAGS_kcov.o := $(call cc-option, -fno-conserve-stack) -fno-stack-protector
|
||||
|
||||
obj-y += sched/
|
||||
|
@ -381,9 +381,7 @@ static comp2_t encode_comp2_t(u64 value)
|
||||
return (value & (MAXFRACT2>>1)) | (exp << (MANTSIZE2-1));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ACCT_VERSION == 3
|
||||
#elif ACCT_VERSION == 3
|
||||
/*
|
||||
* encode an u64 into a 32 bit IEEE float
|
||||
*/
|
||||
@ -500,8 +498,7 @@ static void do_acct_process(struct bsd_acct_struct *acct)
|
||||
/* backward-compatible 16 bit fields */
|
||||
ac.ac_uid16 = ac.ac_uid;
|
||||
ac.ac_gid16 = ac.ac_gid;
|
||||
#endif
|
||||
#if ACCT_VERSION == 3
|
||||
#elif ACCT_VERSION == 3
|
||||
{
|
||||
struct pid_namespace *ns = acct->ns;
|
||||
|
||||
|
@ -447,6 +447,7 @@ static int __init crash_save_vmcoreinfo_init(void)
|
||||
VMCOREINFO_PAGESIZE(PAGE_SIZE);
|
||||
|
||||
VMCOREINFO_SYMBOL(init_uts_ns);
|
||||
VMCOREINFO_OFFSET(uts_namespace, name);
|
||||
VMCOREINFO_SYMBOL(node_online_map);
|
||||
#ifdef CONFIG_MMU
|
||||
VMCOREINFO_SYMBOL_ARRAY(swapper_pg_dir);
|
||||
|
@ -37,9 +37,7 @@ static unsigned long adjust_error_retval(unsigned long addr, unsigned long retv)
|
||||
{
|
||||
switch (get_injectable_error_type(addr)) {
|
||||
case EI_ETYPE_NULL:
|
||||
if (retv != 0)
|
||||
return 0;
|
||||
break;
|
||||
return 0;
|
||||
case EI_ETYPE_ERRNO:
|
||||
if (retv < (unsigned long)-MAX_ERRNO)
|
||||
return (unsigned long)-EINVAL;
|
||||
@ -48,6 +46,8 @@ static unsigned long adjust_error_retval(unsigned long addr, unsigned long retv)
|
||||
if (retv != 0 && retv < (unsigned long)-MAX_ERRNO)
|
||||
return (unsigned long)-EINVAL;
|
||||
break;
|
||||
case EI_ETYPE_TRUE:
|
||||
return 1;
|
||||
}
|
||||
|
||||
return retv;
|
||||
|
@ -25,10 +25,8 @@
|
||||
#define GCOV_COUNTERS 9
|
||||
#elif (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
|
||||
#define GCOV_COUNTERS 10
|
||||
#elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9
|
||||
#define GCOV_COUNTERS 9
|
||||
#else
|
||||
#define GCOV_COUNTERS 8
|
||||
#define GCOV_COUNTERS 9
|
||||
#endif
|
||||
|
||||
#define GCOV_TAG_FUNCTION_LENGTH 3
|
||||
@ -229,10 +227,10 @@ int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2)
|
||||
|
||||
/**
|
||||
* gcov_info_add - add up profiling data
|
||||
* @dest: profiling data set to which data is added
|
||||
* @source: profiling data set which is added
|
||||
* @dst: profiling data set to which data is added
|
||||
* @src: profiling data set which is added
|
||||
*
|
||||
* Adds profiling counts of @source to @dest.
|
||||
* Adds profiling counts of @src to @dst.
|
||||
*/
|
||||
void gcov_info_add(struct gcov_info *dst, struct gcov_info *src)
|
||||
{
|
||||
|
244
kernel/reboot.c
244
kernel/reboot.c
@ -553,20 +553,24 @@ static int __init reboot_setup(char *str)
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (isdigit(*(str+1)))
|
||||
reboot_cpu = simple_strtoul(str+1, NULL, 0);
|
||||
else if (str[1] == 'm' && str[2] == 'p' &&
|
||||
isdigit(*(str+3)))
|
||||
reboot_cpu = simple_strtoul(str+3, NULL, 0);
|
||||
else
|
||||
/*
|
||||
* reboot_cpu is s[mp]#### with #### being the processor
|
||||
* to be used for rebooting. Skip 's' or 'smp' prefix.
|
||||
*/
|
||||
str += str[1] == 'm' && str[2] == 'p' ? 3 : 1;
|
||||
|
||||
if (isdigit(str[0])) {
|
||||
int cpu = simple_strtoul(str, NULL, 0);
|
||||
|
||||
if (cpu >= num_possible_cpus()) {
|
||||
pr_err("Ignoring the CPU number in reboot= option. "
|
||||
"CPU %d exceeds possible cpu number %d\n",
|
||||
cpu, num_possible_cpus());
|
||||
break;
|
||||
}
|
||||
reboot_cpu = cpu;
|
||||
} else
|
||||
*mode = REBOOT_SOFT;
|
||||
if (reboot_cpu >= num_possible_cpus()) {
|
||||
pr_err("Ignoring the CPU number in reboot= option. "
|
||||
"CPU %d exceeds possible cpu number %d\n",
|
||||
reboot_cpu, num_possible_cpus());
|
||||
reboot_cpu = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
@ -596,3 +600,217 @@ static int __init reboot_setup(char *str)
|
||||
return 1;
|
||||
}
|
||||
__setup("reboot=", reboot_setup);
|
||||
|
||||
#ifdef CONFIG_SYSFS
|
||||
|
||||
#define REBOOT_COLD_STR "cold"
|
||||
#define REBOOT_WARM_STR "warm"
|
||||
#define REBOOT_HARD_STR "hard"
|
||||
#define REBOOT_SOFT_STR "soft"
|
||||
#define REBOOT_GPIO_STR "gpio"
|
||||
#define REBOOT_UNDEFINED_STR "undefined"
|
||||
|
||||
#define BOOT_TRIPLE_STR "triple"
|
||||
#define BOOT_KBD_STR "kbd"
|
||||
#define BOOT_BIOS_STR "bios"
|
||||
#define BOOT_ACPI_STR "acpi"
|
||||
#define BOOT_EFI_STR "efi"
|
||||
#define BOOT_PCI_STR "pci"
|
||||
|
||||
static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
switch (reboot_mode) {
|
||||
case REBOOT_COLD:
|
||||
val = REBOOT_COLD_STR;
|
||||
break;
|
||||
case REBOOT_WARM:
|
||||
val = REBOOT_WARM_STR;
|
||||
break;
|
||||
case REBOOT_HARD:
|
||||
val = REBOOT_HARD_STR;
|
||||
break;
|
||||
case REBOOT_SOFT:
|
||||
val = REBOOT_SOFT_STR;
|
||||
break;
|
||||
case REBOOT_GPIO:
|
||||
val = REBOOT_GPIO_STR;
|
||||
break;
|
||||
default:
|
||||
val = REBOOT_UNDEFINED_STR;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", val);
|
||||
}
|
||||
static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
if (!capable(CAP_SYS_BOOT))
|
||||
return -EPERM;
|
||||
|
||||
if (!strncmp(buf, REBOOT_COLD_STR, strlen(REBOOT_COLD_STR)))
|
||||
reboot_mode = REBOOT_COLD;
|
||||
else if (!strncmp(buf, REBOOT_WARM_STR, strlen(REBOOT_WARM_STR)))
|
||||
reboot_mode = REBOOT_WARM;
|
||||
else if (!strncmp(buf, REBOOT_HARD_STR, strlen(REBOOT_HARD_STR)))
|
||||
reboot_mode = REBOOT_HARD;
|
||||
else if (!strncmp(buf, REBOOT_SOFT_STR, strlen(REBOOT_SOFT_STR)))
|
||||
reboot_mode = REBOOT_SOFT;
|
||||
else if (!strncmp(buf, REBOOT_GPIO_STR, strlen(REBOOT_GPIO_STR)))
|
||||
reboot_mode = REBOOT_GPIO;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
reboot_default = 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
static struct kobj_attribute reboot_mode_attr = __ATTR_RW(mode);
|
||||
|
||||
#ifdef CONFIG_X86
|
||||
static ssize_t force_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", reboot_force);
|
||||
}
|
||||
static ssize_t force_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
bool res;
|
||||
|
||||
if (!capable(CAP_SYS_BOOT))
|
||||
return -EPERM;
|
||||
|
||||
if (kstrtobool(buf, &res))
|
||||
return -EINVAL;
|
||||
|
||||
reboot_default = 0;
|
||||
reboot_force = res;
|
||||
|
||||
return count;
|
||||
}
|
||||
static struct kobj_attribute reboot_force_attr = __ATTR_RW(force);
|
||||
|
||||
static ssize_t type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
const char *val;
|
||||
|
||||
switch (reboot_type) {
|
||||
case BOOT_TRIPLE:
|
||||
val = BOOT_TRIPLE_STR;
|
||||
break;
|
||||
case BOOT_KBD:
|
||||
val = BOOT_KBD_STR;
|
||||
break;
|
||||
case BOOT_BIOS:
|
||||
val = BOOT_BIOS_STR;
|
||||
break;
|
||||
case BOOT_ACPI:
|
||||
val = BOOT_ACPI_STR;
|
||||
break;
|
||||
case BOOT_EFI:
|
||||
val = BOOT_EFI_STR;
|
||||
break;
|
||||
case BOOT_CF9_FORCE:
|
||||
val = BOOT_PCI_STR;
|
||||
break;
|
||||
default:
|
||||
val = REBOOT_UNDEFINED_STR;
|
||||
}
|
||||
|
||||
return sprintf(buf, "%s\n", val);
|
||||
}
|
||||
static ssize_t type_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
if (!capable(CAP_SYS_BOOT))
|
||||
return -EPERM;
|
||||
|
||||
if (!strncmp(buf, BOOT_TRIPLE_STR, strlen(BOOT_TRIPLE_STR)))
|
||||
reboot_type = BOOT_TRIPLE;
|
||||
else if (!strncmp(buf, BOOT_KBD_STR, strlen(BOOT_KBD_STR)))
|
||||
reboot_type = BOOT_KBD;
|
||||
else if (!strncmp(buf, BOOT_BIOS_STR, strlen(BOOT_BIOS_STR)))
|
||||
reboot_type = BOOT_BIOS;
|
||||
else if (!strncmp(buf, BOOT_ACPI_STR, strlen(BOOT_ACPI_STR)))
|
||||
reboot_type = BOOT_ACPI;
|
||||
else if (!strncmp(buf, BOOT_EFI_STR, strlen(BOOT_EFI_STR)))
|
||||
reboot_type = BOOT_EFI;
|
||||
else if (!strncmp(buf, BOOT_PCI_STR, strlen(BOOT_PCI_STR)))
|
||||
reboot_type = BOOT_CF9_FORCE;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
reboot_default = 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
static struct kobj_attribute reboot_type_attr = __ATTR_RW(type);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static ssize_t cpu_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%d\n", reboot_cpu);
|
||||
}
|
||||
static ssize_t cpu_store(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned int cpunum;
|
||||
int rc;
|
||||
|
||||
if (!capable(CAP_SYS_BOOT))
|
||||
return -EPERM;
|
||||
|
||||
rc = kstrtouint(buf, 0, &cpunum);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (cpunum >= num_possible_cpus())
|
||||
return -ERANGE;
|
||||
|
||||
reboot_default = 0;
|
||||
reboot_cpu = cpunum;
|
||||
|
||||
return count;
|
||||
}
|
||||
static struct kobj_attribute reboot_cpu_attr = __ATTR_RW(cpu);
|
||||
#endif
|
||||
|
||||
static struct attribute *reboot_attrs[] = {
|
||||
&reboot_mode_attr.attr,
|
||||
#ifdef CONFIG_X86
|
||||
&reboot_force_attr.attr,
|
||||
&reboot_type_attr.attr,
|
||||
#endif
|
||||
#ifdef CONFIG_SMP
|
||||
&reboot_cpu_attr.attr,
|
||||
#endif
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group reboot_attr_group = {
|
||||
.attrs = reboot_attrs,
|
||||
};
|
||||
|
||||
static int __init reboot_ksysfs_init(void)
|
||||
{
|
||||
struct kobject *reboot_kobj;
|
||||
int ret;
|
||||
|
||||
reboot_kobj = kobject_create_and_add("reboot", kernel_kobj);
|
||||
if (!reboot_kobj)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = sysfs_create_group(reboot_kobj, &reboot_attr_group);
|
||||
if (ret) {
|
||||
kobject_put(reboot_kobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(reboot_ksysfs_init);
|
||||
|
||||
#endif
|
||||
|
109
kernel/relay.c
109
kernel/relay.c
@ -27,15 +27,6 @@
|
||||
static DEFINE_MUTEX(relay_channels_mutex);
|
||||
static LIST_HEAD(relay_channels);
|
||||
|
||||
/*
|
||||
* close() vm_op implementation for relay file mapping.
|
||||
*/
|
||||
static void relay_file_mmap_close(struct vm_area_struct *vma)
|
||||
{
|
||||
struct rchan_buf *buf = vma->vm_private_data;
|
||||
buf->chan->cb->buf_unmapped(buf, vma->vm_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* fault() vm_op implementation for relay file mapping.
|
||||
*/
|
||||
@ -62,7 +53,6 @@ static vm_fault_t relay_buf_fault(struct vm_fault *vmf)
|
||||
*/
|
||||
static const struct vm_operations_struct relay_file_mmap_ops = {
|
||||
.fault = relay_buf_fault,
|
||||
.close = relay_file_mmap_close,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -96,7 +86,6 @@ static void relay_free_page_array(struct page **array)
|
||||
static int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
|
||||
{
|
||||
unsigned long length = vma->vm_end - vma->vm_start;
|
||||
struct file *filp = vma->vm_file;
|
||||
|
||||
if (!buf)
|
||||
return -EBADF;
|
||||
@ -107,7 +96,6 @@ static int relay_mmap_buf(struct rchan_buf *buf, struct vm_area_struct *vma)
|
||||
vma->vm_ops = &relay_file_mmap_ops;
|
||||
vma->vm_flags |= VM_DONTEXPAND;
|
||||
vma->vm_private_data = buf;
|
||||
buf->chan->cb->buf_mapped(buf, filp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -264,70 +252,16 @@ EXPORT_SYMBOL_GPL(relay_buf_full);
|
||||
* High-level relay kernel API and associated functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* rchan_callback implementations defining default channel behavior. Used
|
||||
* in place of corresponding NULL values in client callback struct.
|
||||
*/
|
||||
|
||||
/*
|
||||
* subbuf_start() default callback. Does nothing.
|
||||
*/
|
||||
static int subbuf_start_default_callback (struct rchan_buf *buf,
|
||||
void *subbuf,
|
||||
void *prev_subbuf,
|
||||
size_t prev_padding)
|
||||
static int relay_subbuf_start(struct rchan_buf *buf, void *subbuf,
|
||||
void *prev_subbuf, size_t prev_padding)
|
||||
{
|
||||
if (relay_buf_full(buf))
|
||||
return 0;
|
||||
if (!buf->chan->cb->subbuf_start)
|
||||
return !relay_buf_full(buf);
|
||||
|
||||
return 1;
|
||||
return buf->chan->cb->subbuf_start(buf, subbuf,
|
||||
prev_subbuf, prev_padding);
|
||||
}
|
||||
|
||||
/*
|
||||
* buf_mapped() default callback. Does nothing.
|
||||
*/
|
||||
static void buf_mapped_default_callback(struct rchan_buf *buf,
|
||||
struct file *filp)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* buf_unmapped() default callback. Does nothing.
|
||||
*/
|
||||
static void buf_unmapped_default_callback(struct rchan_buf *buf,
|
||||
struct file *filp)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* create_buf_file_create() default callback. Does nothing.
|
||||
*/
|
||||
static struct dentry *create_buf_file_default_callback(const char *filename,
|
||||
struct dentry *parent,
|
||||
umode_t mode,
|
||||
struct rchan_buf *buf,
|
||||
int *is_global)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* remove_buf_file() default callback. Does nothing.
|
||||
*/
|
||||
static int remove_buf_file_default_callback(struct dentry *dentry)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* relay channel default callbacks */
|
||||
static struct rchan_callbacks default_channel_callbacks = {
|
||||
.subbuf_start = subbuf_start_default_callback,
|
||||
.buf_mapped = buf_mapped_default_callback,
|
||||
.buf_unmapped = buf_unmapped_default_callback,
|
||||
.create_buf_file = create_buf_file_default_callback,
|
||||
.remove_buf_file = remove_buf_file_default_callback,
|
||||
};
|
||||
|
||||
/**
|
||||
* wakeup_readers - wake up readers waiting on a channel
|
||||
* @work: contains the channel buffer
|
||||
@ -371,7 +305,7 @@ static void __relay_reset(struct rchan_buf *buf, unsigned int init)
|
||||
for (i = 0; i < buf->chan->n_subbufs; i++)
|
||||
buf->padding[i] = 0;
|
||||
|
||||
buf->chan->cb->subbuf_start(buf, buf->data, NULL, 0);
|
||||
relay_subbuf_start(buf, buf->data, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -499,27 +433,6 @@ static void relay_close_buf(struct rchan_buf *buf)
|
||||
kref_put(&buf->kref, relay_remove_buf);
|
||||
}
|
||||
|
||||
static void setup_callbacks(struct rchan *chan,
|
||||
struct rchan_callbacks *cb)
|
||||
{
|
||||
if (!cb) {
|
||||
chan->cb = &default_channel_callbacks;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cb->subbuf_start)
|
||||
cb->subbuf_start = subbuf_start_default_callback;
|
||||
if (!cb->buf_mapped)
|
||||
cb->buf_mapped = buf_mapped_default_callback;
|
||||
if (!cb->buf_unmapped)
|
||||
cb->buf_unmapped = buf_unmapped_default_callback;
|
||||
if (!cb->create_buf_file)
|
||||
cb->create_buf_file = create_buf_file_default_callback;
|
||||
if (!cb->remove_buf_file)
|
||||
cb->remove_buf_file = remove_buf_file_default_callback;
|
||||
chan->cb = cb;
|
||||
}
|
||||
|
||||
int relay_prepare_cpu(unsigned int cpu)
|
||||
{
|
||||
struct rchan *chan;
|
||||
@ -565,7 +478,7 @@ struct rchan *relay_open(const char *base_filename,
|
||||
struct dentry *parent,
|
||||
size_t subbuf_size,
|
||||
size_t n_subbufs,
|
||||
struct rchan_callbacks *cb,
|
||||
const struct rchan_callbacks *cb,
|
||||
void *private_data)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -576,6 +489,8 @@ struct rchan *relay_open(const char *base_filename,
|
||||
return NULL;
|
||||
if (subbuf_size > UINT_MAX / n_subbufs)
|
||||
return NULL;
|
||||
if (!cb || !cb->create_buf_file || !cb->remove_buf_file)
|
||||
return NULL;
|
||||
|
||||
chan = kzalloc(sizeof(struct rchan), GFP_KERNEL);
|
||||
if (!chan)
|
||||
@ -597,7 +512,7 @@ struct rchan *relay_open(const char *base_filename,
|
||||
chan->has_base_filename = 1;
|
||||
strlcpy(chan->base_filename, base_filename, NAME_MAX);
|
||||
}
|
||||
setup_callbacks(chan, cb);
|
||||
chan->cb = cb;
|
||||
kref_init(&chan->kref);
|
||||
|
||||
mutex_lock(&relay_channels_mutex);
|
||||
@ -780,7 +695,7 @@ size_t relay_switch_subbuf(struct rchan_buf *buf, size_t length)
|
||||
new_subbuf = buf->subbufs_produced % buf->chan->n_subbufs;
|
||||
new = buf->start + new_subbuf * buf->chan->subbuf_size;
|
||||
buf->offset = 0;
|
||||
if (!buf->chan->cb->subbuf_start(buf, new, old, buf->prev_padding)) {
|
||||
if (!relay_subbuf_start(buf, new, old, buf->prev_padding)) {
|
||||
buf->offset = buf->chan->subbuf_size + 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -320,9 +320,8 @@ int release_resource(struct resource *old)
|
||||
EXPORT_SYMBOL(release_resource);
|
||||
|
||||
/**
|
||||
* Finds the lowest iomem resource that covers part of [@start..@end]. The
|
||||
* caller must specify @start, @end, @flags, and @desc (which may be
|
||||
* IORES_DESC_NONE).
|
||||
* find_next_iomem_res - Finds the lowest iomem resource that covers part of
|
||||
* [@start..@end].
|
||||
*
|
||||
* If a resource is found, returns 0 and @*res is overwritten with the part
|
||||
* of the resource that's within [@start..@end]; if none is found, returns
|
||||
@ -337,6 +336,9 @@ EXPORT_SYMBOL(release_resource);
|
||||
* @desc: descriptor the resource must have
|
||||
* @first_lvl: walk only the first level children, if set
|
||||
* @res: return ptr, if resource found
|
||||
*
|
||||
* The caller must specify @start, @end, @flags, and @desc
|
||||
* (which may be IORES_DESC_NONE).
|
||||
*/
|
||||
static int find_next_iomem_res(resource_size_t start, resource_size_t end,
|
||||
unsigned long flags, unsigned long desc,
|
||||
@ -416,11 +418,9 @@ static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
|
||||
}
|
||||
|
||||
/**
|
||||
* Walks through iomem resources and calls func() with matching resource
|
||||
* ranges. This walks through whole tree and not just first level children.
|
||||
* All the memory ranges which overlap start,end and also match flags and
|
||||
* desc are valid candidates.
|
||||
*
|
||||
* walk_iomem_res_desc - Walks through iomem resources and calls func()
|
||||
* with matching resource ranges.
|
||||
* *
|
||||
* @desc: I/O resource descriptor. Use IORES_DESC_NONE to skip @desc check.
|
||||
* @flags: I/O resource flags
|
||||
* @start: start addr
|
||||
@ -428,6 +428,10 @@ static int __walk_iomem_res_desc(resource_size_t start, resource_size_t end,
|
||||
* @arg: function argument for the callback @func
|
||||
* @func: callback function that is called for each qualifying resource area
|
||||
*
|
||||
* This walks through whole tree and not just first level children.
|
||||
* All the memory ranges which overlap start,end and also match flags and
|
||||
* desc are valid candidates.
|
||||
*
|
||||
* NOTE: For a new descriptor search, define a new IORES_DESC in
|
||||
* <linux/ioport.h> and set it in 'desc' of a target resource entry.
|
||||
*/
|
||||
@ -1372,9 +1376,9 @@ static bool system_ram_resources_mergeable(struct resource *r1,
|
||||
!r1->child && !r2->child;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* merge_system_ram_resource - mark the System RAM resource mergeable and try to
|
||||
* merge it with adjacent, mergeable resources
|
||||
* merge it with adjacent, mergeable resources
|
||||
* @res: resource descriptor
|
||||
*
|
||||
* This interface is intended for memory hotplug, whereby lots of contiguous
|
||||
|
@ -449,7 +449,7 @@ static struct dentry *blk_create_buf_file_callback(const char *filename,
|
||||
&relay_file_operations);
|
||||
}
|
||||
|
||||
static struct rchan_callbacks blk_relay_callbacks = {
|
||||
static const struct rchan_callbacks blk_relay_callbacks = {
|
||||
.subbuf_start = blk_subbuf_start_callback,
|
||||
.create_buf_file = blk_create_buf_file_callback,
|
||||
.remove_buf_file = blk_remove_buf_file_callback,
|
||||
|
@ -2311,6 +2311,17 @@ config LINEAR_RANGES_TEST
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config CMDLINE_KUNIT_TEST
|
||||
tristate "KUnit test for cmdline API"
|
||||
depends on KUNIT
|
||||
help
|
||||
This builds the cmdline API unit test.
|
||||
Tests the logic of API provided by cmdline.c.
|
||||
For more information on KUnit and unit tests in general please refer
|
||||
to the KUnit documentation in Documentation/dev-tools/kunit/.
|
||||
|
||||
If unsure, say N.
|
||||
|
||||
config BITS_TEST
|
||||
tristate "KUnit test for bits.h"
|
||||
depends on KUNIT
|
||||
|
@ -14,6 +14,7 @@ if UBSAN
|
||||
|
||||
config UBSAN_TRAP
|
||||
bool "On Sanitizer warnings, abort the running kernel code"
|
||||
depends on !COMPILE_TEST
|
||||
depends on $(cc-option, -fsanitize-undefined-trap-on-error)
|
||||
help
|
||||
Building kernels with Sanitizer features enabled tends to grow
|
||||
@ -36,10 +37,17 @@ config UBSAN_KCOV_BROKEN
|
||||
See https://bugs.llvm.org/show_bug.cgi?id=45831 for the status
|
||||
in newer releases.
|
||||
|
||||
config CC_HAS_UBSAN_BOUNDS
|
||||
def_bool $(cc-option,-fsanitize=bounds)
|
||||
|
||||
config CC_HAS_UBSAN_ARRAY_BOUNDS
|
||||
def_bool $(cc-option,-fsanitize=array-bounds)
|
||||
|
||||
config UBSAN_BOUNDS
|
||||
bool "Perform array index bounds checking"
|
||||
default UBSAN
|
||||
depends on !UBSAN_KCOV_BROKEN
|
||||
depends on CC_HAS_UBSAN_ARRAY_BOUNDS || CC_HAS_UBSAN_BOUNDS
|
||||
help
|
||||
This option enables detection of directly indexed out of bounds
|
||||
array accesses, where the array size is known at compile time.
|
||||
@ -47,36 +55,121 @@ config UBSAN_BOUNDS
|
||||
to the {str,mem}*cpy() family of functions (that is addressed
|
||||
by CONFIG_FORTIFY_SOURCE).
|
||||
|
||||
config UBSAN_ONLY_BOUNDS
|
||||
def_bool CC_HAS_UBSAN_BOUNDS && !CC_HAS_UBSAN_ARRAY_BOUNDS
|
||||
depends on UBSAN_BOUNDS
|
||||
help
|
||||
This is a weird case: Clang's -fsanitize=bounds includes
|
||||
-fsanitize=local-bounds, but it's trapping-only, so for
|
||||
Clang, we must use -fsanitize=array-bounds when we want
|
||||
traditional array bounds checking enabled. For GCC, we
|
||||
want -fsanitize=bounds.
|
||||
|
||||
config UBSAN_ARRAY_BOUNDS
|
||||
def_bool CC_HAS_UBSAN_ARRAY_BOUNDS
|
||||
depends on UBSAN_BOUNDS
|
||||
|
||||
config UBSAN_LOCAL_BOUNDS
|
||||
bool "Perform array local bounds checking"
|
||||
depends on UBSAN_TRAP
|
||||
depends on CC_IS_CLANG
|
||||
depends on !UBSAN_KCOV_BROKEN
|
||||
depends on $(cc-option,-fsanitize=local-bounds)
|
||||
help
|
||||
This option enables -fsanitize=local-bounds which traps when an
|
||||
exception/error is detected. Therefore, it should be enabled only
|
||||
if trapping is expected.
|
||||
exception/error is detected. Therefore, it may only be enabled
|
||||
with CONFIG_UBSAN_TRAP.
|
||||
|
||||
Enabling this option detects errors due to accesses through a
|
||||
pointer that is derived from an object of a statically-known size,
|
||||
where an added offset (which may not be known statically) is
|
||||
out-of-bounds.
|
||||
|
||||
config UBSAN_MISC
|
||||
bool "Enable all other Undefined Behavior sanity checks"
|
||||
config UBSAN_SHIFT
|
||||
bool "Perform checking for bit-shift overflows"
|
||||
default UBSAN
|
||||
depends on $(cc-option,-fsanitize=shift)
|
||||
help
|
||||
This option enables all sanity checks that don't have their
|
||||
own Kconfig options. Disable this if you only want to have
|
||||
individually selected checks.
|
||||
This option enables -fsanitize=shift which checks for bit-shift
|
||||
operations that overflow to the left or go switch to negative
|
||||
for signed types.
|
||||
|
||||
config UBSAN_DIV_ZERO
|
||||
bool "Perform checking for integer divide-by-zero"
|
||||
depends on $(cc-option,-fsanitize=integer-divide-by-zero)
|
||||
help
|
||||
This option enables -fsanitize=integer-divide-by-zero which checks
|
||||
for integer division by zero. This is effectively redundant with the
|
||||
kernel's existing exception handling, though it can provide greater
|
||||
debugging information under CONFIG_UBSAN_REPORT_FULL.
|
||||
|
||||
config UBSAN_UNREACHABLE
|
||||
bool "Perform checking for unreachable code"
|
||||
# objtool already handles unreachable checking and gets angry about
|
||||
# seeing UBSan instrumentation located in unreachable places.
|
||||
depends on !STACK_VALIDATION
|
||||
depends on $(cc-option,-fsanitize=unreachable)
|
||||
help
|
||||
This option enables -fsanitize=unreachable which checks for control
|
||||
flow reaching an expected-to-be-unreachable position.
|
||||
|
||||
config UBSAN_SIGNED_OVERFLOW
|
||||
bool "Perform checking for signed arithmetic overflow"
|
||||
default UBSAN
|
||||
depends on $(cc-option,-fsanitize=signed-integer-overflow)
|
||||
help
|
||||
This option enables -fsanitize=signed-integer-overflow which checks
|
||||
for overflow of any arithmetic operations with signed integers.
|
||||
|
||||
config UBSAN_UNSIGNED_OVERFLOW
|
||||
bool "Perform checking for unsigned arithmetic overflow"
|
||||
depends on $(cc-option,-fsanitize=unsigned-integer-overflow)
|
||||
help
|
||||
This option enables -fsanitize=unsigned-integer-overflow which checks
|
||||
for overflow of any arithmetic operations with unsigned integers. This
|
||||
currently causes x86 to fail to boot.
|
||||
|
||||
config UBSAN_OBJECT_SIZE
|
||||
bool "Perform checking for accesses beyond the end of objects"
|
||||
default UBSAN
|
||||
# gcc hugely expands stack usage with -fsanitize=object-size
|
||||
# https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/
|
||||
depends on !CC_IS_GCC
|
||||
depends on $(cc-option,-fsanitize=object-size)
|
||||
help
|
||||
This option enables -fsanitize=object-size which checks for accesses
|
||||
beyond the end of objects where the optimizer can determine both the
|
||||
object being operated on and its size, usually seen with bad downcasts,
|
||||
or access to struct members from NULL pointers.
|
||||
|
||||
config UBSAN_BOOL
|
||||
bool "Perform checking for non-boolean values used as boolean"
|
||||
default UBSAN
|
||||
depends on $(cc-option,-fsanitize=bool)
|
||||
help
|
||||
This option enables -fsanitize=bool which checks for boolean values being
|
||||
loaded that are neither 0 nor 1.
|
||||
|
||||
config UBSAN_ENUM
|
||||
bool "Perform checking for out of bounds enum values"
|
||||
default UBSAN
|
||||
depends on $(cc-option,-fsanitize=enum)
|
||||
help
|
||||
This option enables -fsanitize=enum which checks for values being loaded
|
||||
into an enum that are outside the range of given values for the given enum.
|
||||
|
||||
config UBSAN_ALIGNMENT
|
||||
bool "Perform checking for misaligned pointer usage"
|
||||
default !HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
depends on !UBSAN_TRAP && !COMPILE_TEST
|
||||
depends on $(cc-option,-fsanitize=alignment)
|
||||
help
|
||||
This option enables the check of unaligned memory accesses.
|
||||
Enabling this option on architectures that support unaligned
|
||||
accesses may produce a lot of false positives.
|
||||
|
||||
config UBSAN_SANITIZE_ALL
|
||||
bool "Enable instrumentation for the entire kernel"
|
||||
depends on ARCH_HAS_UBSAN_SANITIZE_ALL
|
||||
|
||||
# We build with -Wno-maybe-uninitilzed, but we still want to
|
||||
# use -Wmaybe-uninitilized in allmodconfig builds.
|
||||
# So dependsy bellow used to disable this option in allmodconfig
|
||||
depends on !COMPILE_TEST
|
||||
default y
|
||||
help
|
||||
This option activates instrumentation for the entire kernel.
|
||||
@ -85,15 +178,6 @@ config UBSAN_SANITIZE_ALL
|
||||
Enabling this option will get kernel image size increased
|
||||
significantly.
|
||||
|
||||
config UBSAN_ALIGNMENT
|
||||
bool "Enable checks for pointers alignment"
|
||||
default !HAVE_EFFICIENT_UNALIGNED_ACCESS
|
||||
depends on !UBSAN_TRAP
|
||||
help
|
||||
This option enables the check of unaligned memory accesses.
|
||||
Enabling this option on architectures that support unaligned
|
||||
accesses may produce a lot of false positives.
|
||||
|
||||
config TEST_UBSAN
|
||||
tristate "Module for testing for undefined behavior detection"
|
||||
depends on m
|
||||
|
@ -353,3 +353,4 @@ obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o
|
||||
obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
|
||||
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
|
||||
obj-$(CONFIG_BITS_TEST) += test_bits.o
|
||||
obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o
|
||||
|
@ -35,25 +35,37 @@ static int get_range(char **str, int *pint, int n)
|
||||
/**
|
||||
* get_option - Parse integer from an option string
|
||||
* @str: option string
|
||||
* @pint: (output) integer value parsed from @str
|
||||
* @pint: (optional output) integer value parsed from @str
|
||||
*
|
||||
* Read an int from an option string; if available accept a subsequent
|
||||
* comma as well.
|
||||
*
|
||||
* When @pint is NULL the function can be used as a validator of
|
||||
* the current option in the string.
|
||||
*
|
||||
* Return values:
|
||||
* 0 - no int in string
|
||||
* 1 - int found, no subsequent comma
|
||||
* 2 - int found including a subsequent comma
|
||||
* 3 - hyphen found to denote a range
|
||||
*
|
||||
* Leading hyphen without integer is no integer case, but we consume it
|
||||
* for the sake of simplification.
|
||||
*/
|
||||
|
||||
int get_option(char **str, int *pint)
|
||||
{
|
||||
char *cur = *str;
|
||||
int value;
|
||||
|
||||
if (!cur || !(*cur))
|
||||
return 0;
|
||||
*pint = simple_strtol(cur, str, 0);
|
||||
if (*cur == '-')
|
||||
value = -simple_strtoull(++cur, str, 0);
|
||||
else
|
||||
value = simple_strtoull(cur, str, 0);
|
||||
if (pint)
|
||||
*pint = value;
|
||||
if (cur == *str)
|
||||
return 0;
|
||||
if (**str == ',') {
|
||||
|
100
lib/cmdline_kunit.c
Normal file
100
lib/cmdline_kunit.c
Normal file
@ -0,0 +1,100 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Test cases for API provided by cmdline.c
|
||||
*/
|
||||
|
||||
#include <kunit/test.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
static const char *cmdline_test_strings[] = {
|
||||
"\"\"", "" , "=" , "\"-", "," , "-," , ",-" , "-" ,
|
||||
"+," , "--", ",,", "''" , "\"\",", "\",\"", "-\"\"", "\"",
|
||||
};
|
||||
|
||||
static const int cmdline_test_values[] = {
|
||||
1, 1, 1, 1, 2, 3, 2, 3,
|
||||
1, 3, 2, 1, 1, 1, 3, 1,
|
||||
};
|
||||
|
||||
static void cmdline_do_one_test(struct kunit *test, const char *in, int rc, int offset)
|
||||
{
|
||||
const char *fmt = "Pattern: %s";
|
||||
const char *out = in;
|
||||
int dummy;
|
||||
int ret;
|
||||
|
||||
ret = get_option((char **)&out, &dummy);
|
||||
|
||||
KUNIT_EXPECT_EQ_MSG(test, ret, rc, fmt, in);
|
||||
KUNIT_EXPECT_PTR_EQ_MSG(test, out, in + offset, fmt, in);
|
||||
}
|
||||
|
||||
static void cmdline_test_noint(struct kunit *test)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
do {
|
||||
const char *str = cmdline_test_strings[i];
|
||||
int rc = 0;
|
||||
int offset;
|
||||
|
||||
/* Only first and leading '-' will advance the pointer */
|
||||
offset = !!(*str == '-');
|
||||
cmdline_do_one_test(test, str, rc, offset);
|
||||
} while (++i < ARRAY_SIZE(cmdline_test_strings));
|
||||
}
|
||||
|
||||
static void cmdline_test_lead_int(struct kunit *test)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
char in[32];
|
||||
|
||||
do {
|
||||
const char *str = cmdline_test_strings[i];
|
||||
int rc = cmdline_test_values[i];
|
||||
int offset;
|
||||
|
||||
sprintf(in, "%u%s", get_random_int() % 256, str);
|
||||
/* Only first '-' after the number will advance the pointer */
|
||||
offset = strlen(in) - strlen(str) + !!(rc == 2);
|
||||
cmdline_do_one_test(test, in, rc, offset);
|
||||
} while (++i < ARRAY_SIZE(cmdline_test_strings));
|
||||
}
|
||||
|
||||
static void cmdline_test_tail_int(struct kunit *test)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
char in[32];
|
||||
|
||||
do {
|
||||
const char *str = cmdline_test_strings[i];
|
||||
/* When "" or "-" the result will be valid integer */
|
||||
int rc = strcmp(str, "") ? (strcmp(str, "-") ? 0 : 1) : 1;
|
||||
int offset;
|
||||
|
||||
sprintf(in, "%s%u", str, get_random_int() % 256);
|
||||
/*
|
||||
* Only first and leading '-' not followed by integer
|
||||
* will advance the pointer.
|
||||
*/
|
||||
offset = rc ? strlen(in) : !!(*str == '-');
|
||||
cmdline_do_one_test(test, in, rc, offset);
|
||||
} while (++i < ARRAY_SIZE(cmdline_test_strings));
|
||||
}
|
||||
|
||||
static struct kunit_case cmdline_test_cases[] = {
|
||||
KUNIT_CASE(cmdline_test_noint),
|
||||
KUNIT_CASE(cmdline_test_lead_int),
|
||||
KUNIT_CASE(cmdline_test_tail_int),
|
||||
{}
|
||||
};
|
||||
|
||||
static struct kunit_suite cmdline_test_suite = {
|
||||
.name = "cmdline",
|
||||
.test_cases = cmdline_test_cases,
|
||||
};
|
||||
kunit_test_suite(cmdline_test_suite);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
@ -3,6 +3,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/errname.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
|
||||
/*
|
||||
* Ensure these tables do not accidentally become gigantic if some
|
||||
|
@ -180,6 +180,8 @@ static const char *error_type_string(int etype)
|
||||
return "ERRNO";
|
||||
case EI_ETYPE_ERRNO_NULL:
|
||||
return "ERRNO_NULL";
|
||||
case EI_ETYPE_TRUE:
|
||||
return "TRUE";
|
||||
default:
|
||||
return "(unknown)";
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <linux/bug.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/errseq.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
/*
|
||||
* An errseq_t is a way of recording errors in one place, and allowing any
|
||||
|
@ -15,8 +15,9 @@
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bitmap.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/swab.h>
|
||||
|
||||
#if !defined(find_next_bit) || !defined(find_next_zero_bit) || \
|
||||
!defined(find_next_bit_le) || !defined(find_next_zero_bit_le) || \
|
||||
|
@ -263,7 +263,11 @@ static FORCE_INLINE int LZ4_decompress_generic(
|
||||
}
|
||||
}
|
||||
|
||||
LZ4_memcpy(op, ip, length);
|
||||
/*
|
||||
* supports overlapping memory regions; only matters
|
||||
* for in-place decompression scenarios
|
||||
*/
|
||||
LZ4_memmove(op, ip, length);
|
||||
ip += length;
|
||||
op += length;
|
||||
|
||||
|
@ -146,6 +146,7 @@ static FORCE_INLINE void LZ4_writeLE16(void *memPtr, U16 value)
|
||||
* environments. This is needed when decompressing the Linux Kernel, for example.
|
||||
*/
|
||||
#define LZ4_memcpy(dst, src, size) __builtin_memcpy(dst, src, size)
|
||||
#define LZ4_memmove(dst, src, size) __builtin_memmove(dst, src, size)
|
||||
|
||||
static FORCE_INLINE void LZ4_copy8(void *dst, const void *src)
|
||||
{
|
||||
|
@ -301,7 +301,7 @@ finished_writing_instruction:
|
||||
return in_end - (ii - ti);
|
||||
}
|
||||
|
||||
int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
|
||||
static int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
|
||||
unsigned char *out, size_t *out_len,
|
||||
void *wrkmem, const unsigned char bitstream_version)
|
||||
{
|
||||
|
@ -18,9 +18,11 @@
|
||||
* or by defining a preprocessor macro in arch/include/asm/div64.h.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/math64.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
/* Not needed on 64bit architectures */
|
||||
#if BITS_PER_LONG == 32
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/export.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
|
@ -6,9 +6,10 @@
|
||||
* square root from Guy L. Steele.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/math.h>
|
||||
|
||||
/**
|
||||
* int_sqrt - computes the integer square root
|
||||
|
@ -1,10 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <asm/div64.h>
|
||||
#include <linux/reciprocal_div.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/math.h>
|
||||
#include <linux/minmax.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include <linux/reciprocal_div.h>
|
||||
|
||||
/*
|
||||
* For a description of the algorithm please have a look at
|
||||
|
@ -62,7 +62,7 @@ struct stack_record {
|
||||
u32 hash; /* Hash in the hastable */
|
||||
u32 size; /* Number of frames in the stack */
|
||||
union handle_parts handle;
|
||||
unsigned long entries[1]; /* Variable-sized array of entries. */
|
||||
unsigned long entries[]; /* Variable-sized array of entries. */
|
||||
};
|
||||
|
||||
static void *stack_slabs[STACK_ALLOC_MAX_SLABS];
|
||||
@ -104,9 +104,8 @@ static bool init_stack_slab(void **prealloc)
|
||||
static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
|
||||
u32 hash, void **prealloc, gfp_t alloc_flags)
|
||||
{
|
||||
int required_size = offsetof(struct stack_record, entries) +
|
||||
sizeof(unsigned long) * size;
|
||||
struct stack_record *stack;
|
||||
size_t required_size = struct_size(stack, entries, size);
|
||||
|
||||
required_size = ALIGN(required_size, 1 << STACK_ALLOC_ALIGN);
|
||||
|
||||
@ -136,7 +135,7 @@ static struct stack_record *depot_alloc_stack(unsigned long *entries, int size,
|
||||
stack->handle.slabindex = depot_index;
|
||||
stack->handle.offset = depot_offset >> STACK_ALLOC_ALIGN;
|
||||
stack->handle.valid = 1;
|
||||
memcpy(stack->entries, entries, size * sizeof(unsigned long));
|
||||
memcpy(stack->entries, entries, flex_array_size(stack, entries, size));
|
||||
depot_offset += required_size;
|
||||
|
||||
return stack;
|
||||
@ -155,8 +154,8 @@ static struct stack_record *stack_table[STACK_HASH_SIZE] = {
|
||||
static inline u32 hash_stack(unsigned long *entries, unsigned int size)
|
||||
{
|
||||
return jhash2((u32 *)entries,
|
||||
size * sizeof(unsigned long) / sizeof(u32),
|
||||
STACK_HASH_SEED);
|
||||
array_size(size, sizeof(*entries)) / sizeof(u32),
|
||||
STACK_HASH_SEED);
|
||||
}
|
||||
|
||||
/* Use our own, non-instrumented version of memcmp().
|
||||
|
@ -85,7 +85,6 @@ EXPORT_SYMBOL(strcasecmp);
|
||||
* @dest: Where to copy the string to
|
||||
* @src: Where to copy the string from
|
||||
*/
|
||||
#undef strcpy
|
||||
char *strcpy(char *dest, const char *src)
|
||||
{
|
||||
char *tmp = dest;
|
||||
@ -302,7 +301,6 @@ EXPORT_SYMBOL(stpcpy);
|
||||
* @dest: The string to be appended to
|
||||
* @src: The string to append to it
|
||||
*/
|
||||
#undef strcat
|
||||
char *strcat(char *dest, const char *src)
|
||||
{
|
||||
char *tmp = dest;
|
||||
@ -378,7 +376,6 @@ EXPORT_SYMBOL(strlcat);
|
||||
* @cs: One string
|
||||
* @ct: Another string
|
||||
*/
|
||||
#undef strcmp
|
||||
int strcmp(const char *cs, const char *ct)
|
||||
{
|
||||
unsigned char c1, c2;
|
||||
@ -958,7 +955,6 @@ EXPORT_SYMBOL(memcmp);
|
||||
* while this particular implementation is a simple (tail) call to memcmp, do
|
||||
* not rely on anything but whether the return value is zero or non-zero.
|
||||
*/
|
||||
#undef bcmp
|
||||
int bcmp(const void *a, const void *b, size_t len)
|
||||
{
|
||||
return memcmp(a, b, len);
|
||||
|
@ -364,18 +364,15 @@ static ssize_t test_dev_config_show_int(char *buf, int val)
|
||||
|
||||
static int test_dev_config_update_u8(const char *buf, size_t size, u8 *cfg)
|
||||
{
|
||||
u8 val;
|
||||
int ret;
|
||||
long new;
|
||||
|
||||
ret = kstrtol(buf, 10, &new);
|
||||
ret = kstrtou8(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (new > U8_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&test_fw_mutex);
|
||||
*(u8 *)cfg = new;
|
||||
*(u8 *)cfg = val;
|
||||
mutex_unlock(&test_fw_mutex);
|
||||
|
||||
/* Always return full write size even if we didn't consume all */
|
||||
|
@ -5,6 +5,8 @@
|
||||
* Author: Matthew Wilcox <willy@infradead.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/module.h>
|
||||
@ -26,8 +28,11 @@ static void test_free_pages(gfp_t gfp)
|
||||
|
||||
static int m_in(void)
|
||||
{
|
||||
pr_info("Testing with GFP_KERNEL\n");
|
||||
test_free_pages(GFP_KERNEL);
|
||||
pr_info("Testing with GFP_KERNEL | __GFP_COMP\n");
|
||||
test_free_pages(GFP_KERNEL | __GFP_COMP);
|
||||
pr_info("Test completed\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -877,20 +877,17 @@ static int test_dev_config_update_uint_sync(struct kmod_test_device *test_dev,
|
||||
int (*test_sync)(struct kmod_test_device *test_dev))
|
||||
{
|
||||
int ret;
|
||||
unsigned long new;
|
||||
unsigned int val;
|
||||
unsigned int old_val;
|
||||
|
||||
ret = kstrtoul(buf, 10, &new);
|
||||
ret = kstrtouint(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (new > UINT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&test_dev->config_mutex);
|
||||
|
||||
old_val = *config;
|
||||
*(unsigned int *)config = new;
|
||||
*(unsigned int *)config = val;
|
||||
|
||||
ret = test_sync(test_dev);
|
||||
if (ret) {
|
||||
@ -914,18 +911,18 @@ static int test_dev_config_update_uint_range(struct kmod_test_device *test_dev,
|
||||
unsigned int min,
|
||||
unsigned int max)
|
||||
{
|
||||
unsigned int val;
|
||||
int ret;
|
||||
unsigned long new;
|
||||
|
||||
ret = kstrtoul(buf, 10, &new);
|
||||
ret = kstrtouint(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (new < min || new > max)
|
||||
if (val < min || val > max)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&test_dev->config_mutex);
|
||||
*config = new;
|
||||
*config = val;
|
||||
mutex_unlock(&test_dev->config_mutex);
|
||||
|
||||
/* Always return full write size even if we didn't consume all */
|
||||
@ -936,18 +933,15 @@ static int test_dev_config_update_int(struct kmod_test_device *test_dev,
|
||||
const char *buf, size_t size,
|
||||
int *config)
|
||||
{
|
||||
int val;
|
||||
int ret;
|
||||
long new;
|
||||
|
||||
ret = kstrtol(buf, 10, &new);
|
||||
ret = kstrtoint(buf, 10, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (new < INT_MIN || new > INT_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&test_dev->config_mutex);
|
||||
*config = new;
|
||||
*config = val;
|
||||
mutex_unlock(&test_dev->config_mutex);
|
||||
/* Always return full write size even if we didn't consume all */
|
||||
return size;
|
||||
|
@ -480,6 +480,21 @@ static int __init test_lockup_init(void)
|
||||
return -EINVAL;
|
||||
|
||||
#ifdef CONFIG_DEBUG_SPINLOCK
|
||||
#ifdef CONFIG_PREEMPT_RT
|
||||
if (test_magic(lock_spinlock_ptr,
|
||||
offsetof(spinlock_t, lock.wait_lock.magic),
|
||||
SPINLOCK_MAGIC) ||
|
||||
test_magic(lock_rwlock_ptr,
|
||||
offsetof(rwlock_t, rtmutex.wait_lock.magic),
|
||||
SPINLOCK_MAGIC) ||
|
||||
test_magic(lock_mutex_ptr,
|
||||
offsetof(struct mutex, lock.wait_lock.magic),
|
||||
SPINLOCK_MAGIC) ||
|
||||
test_magic(lock_rwsem_ptr,
|
||||
offsetof(struct rw_semaphore, rtmutex.wait_lock.magic),
|
||||
SPINLOCK_MAGIC))
|
||||
return -EINVAL;
|
||||
#else
|
||||
if (test_magic(lock_spinlock_ptr,
|
||||
offsetof(spinlock_t, rlock.magic),
|
||||
SPINLOCK_MAGIC) ||
|
||||
@ -493,6 +508,7 @@ static int __init test_lockup_init(void)
|
||||
offsetof(struct rw_semaphore, wait_lock.magic),
|
||||
SPINLOCK_MAGIC))
|
||||
return -EINVAL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ((wait_state != TASK_RUNNING ||
|
||||
|
@ -5,32 +5,54 @@
|
||||
|
||||
typedef void(*test_ubsan_fp)(void);
|
||||
|
||||
#define UBSAN_TEST(config, ...) do { \
|
||||
pr_info("%s " __VA_ARGS__ "%s(%s=%s)\n", __func__, \
|
||||
sizeof(" " __VA_ARGS__) > 2 ? " " : "", \
|
||||
#config, IS_ENABLED(config) ? "y" : "n"); \
|
||||
} while (0)
|
||||
|
||||
static void test_ubsan_add_overflow(void)
|
||||
{
|
||||
volatile int val = INT_MAX;
|
||||
volatile unsigned int uval = UINT_MAX;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW);
|
||||
val += 2;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_UNSIGNED_OVERFLOW);
|
||||
uval += 2;
|
||||
}
|
||||
|
||||
static void test_ubsan_sub_overflow(void)
|
||||
{
|
||||
volatile int val = INT_MIN;
|
||||
volatile unsigned int uval = 0;
|
||||
volatile int val2 = 2;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW);
|
||||
val -= val2;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_UNSIGNED_OVERFLOW);
|
||||
uval -= val2;
|
||||
}
|
||||
|
||||
static void test_ubsan_mul_overflow(void)
|
||||
{
|
||||
volatile int val = INT_MAX / 2;
|
||||
volatile unsigned int uval = UINT_MAX / 2;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW);
|
||||
val *= 3;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_UNSIGNED_OVERFLOW);
|
||||
uval *= 3;
|
||||
}
|
||||
|
||||
static void test_ubsan_negate_overflow(void)
|
||||
{
|
||||
volatile int val = INT_MIN;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_SIGNED_OVERFLOW);
|
||||
val = -val;
|
||||
}
|
||||
|
||||
@ -39,37 +61,67 @@ static void test_ubsan_divrem_overflow(void)
|
||||
volatile int val = 16;
|
||||
volatile int val2 = 0;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_DIV_ZERO);
|
||||
val /= val2;
|
||||
}
|
||||
|
||||
static void test_ubsan_shift_out_of_bounds(void)
|
||||
{
|
||||
volatile int val = -1;
|
||||
int val2 = 10;
|
||||
volatile int neg = -1, wrap = 4;
|
||||
int val1 = 10;
|
||||
int val2 = INT_MAX;
|
||||
|
||||
val2 <<= val;
|
||||
UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent");
|
||||
val1 <<= neg;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_SHIFT, "left overflow");
|
||||
val2 <<= wrap;
|
||||
}
|
||||
|
||||
static void test_ubsan_out_of_bounds(void)
|
||||
{
|
||||
volatile int i = 4, j = 5;
|
||||
volatile int i = 4, j = 5, k = -1;
|
||||
volatile char above[4] = { }; /* Protect surrounding memory. */
|
||||
volatile int arr[4];
|
||||
volatile char below[4] = { }; /* Protect surrounding memory. */
|
||||
|
||||
above[0] = below[0];
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "above");
|
||||
arr[j] = i;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_BOUNDS, "below");
|
||||
arr[k] = i;
|
||||
}
|
||||
|
||||
enum ubsan_test_enum {
|
||||
UBSAN_TEST_ZERO = 0,
|
||||
UBSAN_TEST_ONE,
|
||||
UBSAN_TEST_MAX,
|
||||
};
|
||||
|
||||
static void test_ubsan_load_invalid_value(void)
|
||||
{
|
||||
volatile char *dst, *src;
|
||||
bool val, val2, *ptr;
|
||||
char c = 4;
|
||||
enum ubsan_test_enum eval, eval2, *eptr;
|
||||
unsigned char c = 0xff;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_BOOL, "bool");
|
||||
dst = (char *)&val;
|
||||
src = &c;
|
||||
*dst = *src;
|
||||
|
||||
ptr = &val2;
|
||||
val2 = val;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_ENUM, "enum");
|
||||
dst = (char *)&eval;
|
||||
src = &c;
|
||||
*dst = *src;
|
||||
|
||||
eptr = &eval2;
|
||||
eval2 = eval;
|
||||
}
|
||||
|
||||
static void test_ubsan_null_ptr_deref(void)
|
||||
@ -77,6 +129,7 @@ static void test_ubsan_null_ptr_deref(void)
|
||||
volatile int *ptr = NULL;
|
||||
int val;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE);
|
||||
val = *ptr;
|
||||
}
|
||||
|
||||
@ -85,6 +138,7 @@ static void test_ubsan_misaligned_access(void)
|
||||
volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5};
|
||||
volatile int *ptr, val = 6;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_ALIGNMENT);
|
||||
ptr = (int *)(arr + 1);
|
||||
*ptr = val;
|
||||
}
|
||||
@ -95,6 +149,7 @@ static void test_ubsan_object_size_mismatch(void)
|
||||
volatile int val __aligned(8) = 4;
|
||||
volatile long long *ptr, val2;
|
||||
|
||||
UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE);
|
||||
ptr = (long long *)&val;
|
||||
val2 = *ptr;
|
||||
}
|
||||
@ -104,15 +159,19 @@ static const test_ubsan_fp test_ubsan_array[] = {
|
||||
test_ubsan_sub_overflow,
|
||||
test_ubsan_mul_overflow,
|
||||
test_ubsan_negate_overflow,
|
||||
test_ubsan_divrem_overflow,
|
||||
test_ubsan_shift_out_of_bounds,
|
||||
test_ubsan_out_of_bounds,
|
||||
test_ubsan_load_invalid_value,
|
||||
//test_ubsan_null_ptr_deref, /* exclude it because there is a crash */
|
||||
test_ubsan_misaligned_access,
|
||||
test_ubsan_object_size_mismatch,
|
||||
};
|
||||
|
||||
/* Excluded because they Oops the module. */
|
||||
static const test_ubsan_fp skip_ubsan_array[] = {
|
||||
test_ubsan_divrem_overflow,
|
||||
test_ubsan_null_ptr_deref,
|
||||
};
|
||||
|
||||
static int __init test_ubsan_init(void)
|
||||
{
|
||||
unsigned int i;
|
||||
@ -120,7 +179,6 @@ static int __init test_ubsan_init(void)
|
||||
for (i = 0; i < ARRAY_SIZE(test_ubsan_array); i++)
|
||||
test_ubsan_array[i]();
|
||||
|
||||
(void)test_ubsan_null_ptr_deref; /* to avoid unsed-function warning */
|
||||
return 0;
|
||||
}
|
||||
module_init(test_ubsan_init);
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "ubsan.h"
|
||||
|
||||
const char *type_check_kinds[] = {
|
||||
static const char * const type_check_kinds[] = {
|
||||
"load of",
|
||||
"store to",
|
||||
"reference binding to",
|
||||
|
@ -1359,7 +1359,7 @@ static int __wait_on_page_locked_async(struct page *page,
|
||||
else
|
||||
ret = PageLocked(page);
|
||||
/*
|
||||
* If we were succesful now, we know we're still on the
|
||||
* If we were successful now, we know we're still on the
|
||||
* waitqueue as we're still under the lock. This means it's
|
||||
* safe to remove and return success, we know the callback
|
||||
* isn't going to trigger.
|
||||
|
@ -2391,7 +2391,7 @@ static void __split_huge_page_tail(struct page *head, int tail,
|
||||
* Clone page flags before unfreezing refcount.
|
||||
*
|
||||
* After successful get_page_unless_zero() might follow flags change,
|
||||
* for exmaple lock_page() which set PG_waiters.
|
||||
* for example lock_page() which set PG_waiters.
|
||||
*/
|
||||
page_tail->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
|
||||
page_tail->flags |= (head->flags &
|
||||
|
@ -1275,7 +1275,7 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
|
||||
* PTEs are armed with uffd write protection.
|
||||
* Here we can also mark the new huge pmd as
|
||||
* write protected if any of the small ones is
|
||||
* marked but that could bring uknown
|
||||
* marked but that could bring unknown
|
||||
* userfault messages that falls outside of
|
||||
* the registered range. So, just be simple.
|
||||
*/
|
||||
|
@ -871,7 +871,7 @@ int __init_memblock memblock_physmem_add(phys_addr_t base, phys_addr_t size)
|
||||
* @base: base address of the region
|
||||
* @size: size of the region
|
||||
* @set: set or clear the flag
|
||||
* @flag: the flag to udpate
|
||||
* @flag: the flag to update
|
||||
*
|
||||
* This function isolates region [@base, @base + @size), and sets/clears flag
|
||||
*
|
||||
|
36
mm/memory.c
36
mm/memory.c
@ -4707,9 +4707,9 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address)
|
||||
}
|
||||
#endif /* __PAGETABLE_PMD_FOLDED */
|
||||
|
||||
static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
|
||||
struct mmu_notifier_range *range,
|
||||
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
|
||||
int follow_pte(struct mm_struct *mm, unsigned long address,
|
||||
struct mmu_notifier_range *range, pte_t **ptepp, pmd_t **pmdpp,
|
||||
spinlock_t **ptlp)
|
||||
{
|
||||
pgd_t *pgd;
|
||||
p4d_t *p4d;
|
||||
@ -4774,32 +4774,6 @@ out:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static inline int follow_pte(struct mm_struct *mm, unsigned long address,
|
||||
pte_t **ptepp, spinlock_t **ptlp)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* (void) is needed to make gcc happy */
|
||||
(void) __cond_lock(*ptlp,
|
||||
!(res = __follow_pte_pmd(mm, address, NULL,
|
||||
ptepp, NULL, ptlp)));
|
||||
return res;
|
||||
}
|
||||
|
||||
int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
|
||||
struct mmu_notifier_range *range,
|
||||
pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp)
|
||||
{
|
||||
int res;
|
||||
|
||||
/* (void) is needed to make gcc happy */
|
||||
(void) __cond_lock(*ptlp,
|
||||
!(res = __follow_pte_pmd(mm, address, range,
|
||||
ptepp, pmdpp, ptlp)));
|
||||
return res;
|
||||
}
|
||||
EXPORT_SYMBOL(follow_pte_pmd);
|
||||
|
||||
/**
|
||||
* follow_pfn - look up PFN at a user virtual address
|
||||
* @vma: memory mapping
|
||||
@ -4820,7 +4794,7 @@ int follow_pfn(struct vm_area_struct *vma, unsigned long address,
|
||||
if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
|
||||
return ret;
|
||||
|
||||
ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
|
||||
ret = follow_pte(vma->vm_mm, address, NULL, &ptep, NULL, &ptl);
|
||||
if (ret)
|
||||
return ret;
|
||||
*pfn = pte_pfn(*ptep);
|
||||
@ -4841,7 +4815,7 @@ int follow_phys(struct vm_area_struct *vma,
|
||||
if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
|
||||
goto out;
|
||||
|
||||
if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
|
||||
if (follow_pte(vma->vm_mm, address, NULL, &ptep, NULL, &ptl))
|
||||
goto out;
|
||||
pte = *ptep;
|
||||
|
||||
|
@ -1561,7 +1561,7 @@ int __ref offline_pages(unsigned long start_pfn, unsigned long nr_pages)
|
||||
|
||||
/* Mark all sections offline and remove free pages from the buddy. */
|
||||
__offline_isolated_pages(start_pfn, end_pfn);
|
||||
pr_info("Offlined Pages %ld\n", nr_pages);
|
||||
pr_debug("Offlined Pages %ld\n", nr_pages);
|
||||
|
||||
/*
|
||||
* The memory sections are marked offline, and the pageblock flags
|
||||
|
@ -2594,7 +2594,7 @@ static bool migrate_vma_check_page(struct page *page)
|
||||
* will bump the page reference count. Sadly there is no way to
|
||||
* differentiate a regular pin from migration wait. Hence to
|
||||
* avoid 2 racing thread trying to migrate back to CPU to enter
|
||||
* infinite loop (one stoping migration because the other is
|
||||
* infinite loop (one stopping migration because the other is
|
||||
* waiting on pte migration entry). We always return true here.
|
||||
*
|
||||
* FIXME proper solution is to rework migration_entry_wait() so
|
||||
|
@ -34,7 +34,7 @@
|
||||
*
|
||||
* The need callback is used to decide whether extended memory allocation is
|
||||
* needed or not. Sometimes users want to deactivate some features in this
|
||||
* boot and extra memory would be unneccessary. In this case, to avoid
|
||||
* boot and extra memory would be unnecessary. In this case, to avoid
|
||||
* allocating huge chunk of memory, each clients represent their need of
|
||||
* extra memory through the need callback. If one of the need callbacks
|
||||
* returns true, it means that someone needs extra memory so that
|
||||
|
@ -1042,16 +1042,18 @@ int get_swap_pages(int n_goal, swp_entry_t swp_entries[], int entry_size)
|
||||
/* Only single cluster request supported */
|
||||
WARN_ON_ONCE(n_goal > 1 && size == SWAPFILE_CLUSTER);
|
||||
|
||||
spin_lock(&swap_avail_lock);
|
||||
|
||||
avail_pgs = atomic_long_read(&nr_swap_pages) / size;
|
||||
if (avail_pgs <= 0)
|
||||
if (avail_pgs <= 0) {
|
||||
spin_unlock(&swap_avail_lock);
|
||||
goto noswap;
|
||||
}
|
||||
|
||||
n_goal = min3((long)n_goal, (long)SWAP_BATCH, avail_pgs);
|
||||
|
||||
atomic_long_sub(n_goal * size, &nr_swap_pages);
|
||||
|
||||
spin_lock(&swap_avail_lock);
|
||||
|
||||
start_over:
|
||||
node = numa_node_id();
|
||||
plist_for_each_entry_safe(si, next, &swap_avail_heads[node], avail_lists[node]) {
|
||||
@ -1125,14 +1127,13 @@ swp_entry_t get_swap_page_of_type(int type)
|
||||
|
||||
spin_lock(&si->lock);
|
||||
if (si->flags & SWP_WRITEOK) {
|
||||
atomic_long_dec(&nr_swap_pages);
|
||||
/* This is called for allocating swap entry, not cache */
|
||||
offset = scan_swap_map(si, 1);
|
||||
if (offset) {
|
||||
atomic_long_dec(&nr_swap_pages);
|
||||
spin_unlock(&si->lock);
|
||||
return swp_entry(type, offset);
|
||||
}
|
||||
atomic_long_inc(&nr_swap_pages);
|
||||
}
|
||||
spin_unlock(&si->lock);
|
||||
fail:
|
||||
|
@ -1,37 +1,18 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
export CFLAGS_UBSAN :=
|
||||
# Enable available and selected UBSAN features.
|
||||
ubsan-cflags-$(CONFIG_UBSAN_ALIGNMENT) += -fsanitize=alignment
|
||||
ubsan-cflags-$(CONFIG_UBSAN_ONLY_BOUNDS) += -fsanitize=bounds
|
||||
ubsan-cflags-$(CONFIG_UBSAN_ARRAY_BOUNDS) += -fsanitize=array-bounds
|
||||
ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds
|
||||
ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift
|
||||
ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero
|
||||
ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable
|
||||
ubsan-cflags-$(CONFIG_UBSAN_SIGNED_OVERFLOW) += -fsanitize=signed-integer-overflow
|
||||
ubsan-cflags-$(CONFIG_UBSAN_UNSIGNED_OVERFLOW) += -fsanitize=unsigned-integer-overflow
|
||||
ubsan-cflags-$(CONFIG_UBSAN_OBJECT_SIZE) += -fsanitize=object-size
|
||||
ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool
|
||||
ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum
|
||||
ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
|
||||
|
||||
ifdef CONFIG_UBSAN_ALIGNMENT
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment)
|
||||
endif
|
||||
|
||||
ifdef CONFIG_UBSAN_BOUNDS
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
CFLAGS_UBSAN += -fsanitize=array-bounds
|
||||
else
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_UBSAN_LOCAL_BOUNDS
|
||||
CFLAGS_UBSAN += -fsanitize=local-bounds
|
||||
endif
|
||||
|
||||
ifdef CONFIG_UBSAN_MISC
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=shift)
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=integer-divide-by-zero)
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=unreachable)
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow)
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size)
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=bool)
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize=enum)
|
||||
endif
|
||||
|
||||
ifdef CONFIG_UBSAN_TRAP
|
||||
CFLAGS_UBSAN += $(call cc-option, -fsanitize-undefined-trap-on-error)
|
||||
endif
|
||||
|
||||
# -fsanitize=* options makes GCC less smart than usual and
|
||||
# increase number of 'maybe-uninitialized false-positives
|
||||
CFLAGS_UBSAN += $(call cc-option, -Wno-maybe-uninitialized)
|
||||
export CFLAGS_UBSAN := $(ubsan-cflags-y)
|
||||
|
@ -506,6 +506,64 @@ our $signature_tags = qr{(?xi:
|
||||
Cc:
|
||||
)};
|
||||
|
||||
sub edit_distance_min {
|
||||
my (@arr) = @_;
|
||||
my $len = scalar @arr;
|
||||
if ((scalar @arr) < 1) {
|
||||
# if underflow, return
|
||||
return;
|
||||
}
|
||||
my $min = $arr[0];
|
||||
for my $i (0 .. ($len-1)) {
|
||||
if ($arr[$i] < $min) {
|
||||
$min = $arr[$i];
|
||||
}
|
||||
}
|
||||
return $min;
|
||||
}
|
||||
|
||||
sub get_edit_distance {
|
||||
my ($str1, $str2) = @_;
|
||||
$str1 = lc($str1);
|
||||
$str2 = lc($str2);
|
||||
$str1 =~ s/-//g;
|
||||
$str2 =~ s/-//g;
|
||||
my $len1 = length($str1);
|
||||
my $len2 = length($str2);
|
||||
# two dimensional array storing minimum edit distance
|
||||
my @distance;
|
||||
for my $i (0 .. $len1) {
|
||||
for my $j (0 .. $len2) {
|
||||
if ($i == 0) {
|
||||
$distance[$i][$j] = $j;
|
||||
} elsif ($j == 0) {
|
||||
$distance[$i][$j] = $i;
|
||||
} elsif (substr($str1, $i-1, 1) eq substr($str2, $j-1, 1)) {
|
||||
$distance[$i][$j] = $distance[$i - 1][$j - 1];
|
||||
} else {
|
||||
my $dist1 = $distance[$i][$j - 1]; #insert distance
|
||||
my $dist2 = $distance[$i - 1][$j]; # remove
|
||||
my $dist3 = $distance[$i - 1][$j - 1]; #replace
|
||||
$distance[$i][$j] = 1 + edit_distance_min($dist1, $dist2, $dist3);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $distance[$len1][$len2];
|
||||
}
|
||||
|
||||
sub find_standard_signature {
|
||||
my ($sign_off) = @_;
|
||||
my @standard_signature_tags = (
|
||||
'Signed-off-by:', 'Co-developed-by:', 'Acked-by:', 'Tested-by:',
|
||||
'Reviewed-by:', 'Reported-by:', 'Suggested-by:'
|
||||
);
|
||||
foreach my $signature (@standard_signature_tags) {
|
||||
return $signature if (get_edit_distance($sign_off, $signature) <= 2);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
our @typeListMisordered = (
|
||||
qr{char\s+(?:un)?signed},
|
||||
qr{int\s+(?:(?:un)?signed\s+)?short\s},
|
||||
@ -853,6 +911,13 @@ our $declaration_macros = qr{(?x:
|
||||
(?:SKCIPHER_REQUEST|SHASH_DESC|AHASH_REQUEST)_ON_STACK\s*\(
|
||||
)};
|
||||
|
||||
our %allow_repeated_words = (
|
||||
add => '',
|
||||
added => '',
|
||||
bad => '',
|
||||
be => '',
|
||||
);
|
||||
|
||||
sub deparenthesize {
|
||||
my ($string) = @_;
|
||||
return "" if (!defined($string));
|
||||
@ -1152,6 +1217,7 @@ sub parse_email {
|
||||
my ($formatted_email) = @_;
|
||||
|
||||
my $name = "";
|
||||
my $quoted = "";
|
||||
my $name_comment = "";
|
||||
my $address = "";
|
||||
my $comment = "";
|
||||
@ -1183,14 +1249,20 @@ sub parse_email {
|
||||
}
|
||||
}
|
||||
|
||||
$comment = trim($comment);
|
||||
$name = trim($name);
|
||||
$name =~ s/^\"|\"$//g;
|
||||
if ($name =~ s/(\s*\([^\)]+\))\s*//) {
|
||||
$name_comment = trim($1);
|
||||
# Extract comments from names excluding quoted parts
|
||||
# "John D. (Doe)" - Do not extract
|
||||
if ($name =~ s/\"(.+)\"//) {
|
||||
$quoted = $1;
|
||||
}
|
||||
while ($name =~ s/\s*($balanced_parens)\s*/ /) {
|
||||
$name_comment .= trim($1);
|
||||
}
|
||||
$name =~ s/^[ \"]+|[ \"]+$//g;
|
||||
$name = trim("$quoted $name");
|
||||
|
||||
$address = trim($address);
|
||||
$address =~ s/^\<|\>$//g;
|
||||
$comment = trim($comment);
|
||||
|
||||
if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
|
||||
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
|
||||
@ -1205,17 +1277,20 @@ sub format_email {
|
||||
|
||||
my $formatted_email;
|
||||
|
||||
$name_comment = trim($name_comment);
|
||||
$comment = trim($comment);
|
||||
$name = trim($name);
|
||||
$name =~ s/^\"|\"$//g;
|
||||
$name =~ s/^[ \"]+|[ \"]+$//g;
|
||||
$address = trim($address);
|
||||
$address =~ s/(?:\.|\,|\")+$//; ##trailing commas, dots or quotes
|
||||
|
||||
if ($name =~ /[^\w \-]/i) { ##has "must quote" chars
|
||||
$name =~ s/(?<!\\)"/\\"/g; ##escape quotes
|
||||
$name = "\"$name\"";
|
||||
}
|
||||
|
||||
$name_comment = trim($name_comment);
|
||||
$name_comment = " $name_comment" if ($name_comment ne "");
|
||||
$comment = trim($comment);
|
||||
$comment = " $comment" if ($comment ne "");
|
||||
|
||||
if ("$name" eq "") {
|
||||
$formatted_email = "$address";
|
||||
} else {
|
||||
@ -1233,15 +1308,11 @@ sub reformat_email {
|
||||
}
|
||||
|
||||
sub same_email_addresses {
|
||||
my ($email1, $email2, $match_comment) = @_;
|
||||
my ($email1, $email2) = @_;
|
||||
|
||||
my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1);
|
||||
my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2);
|
||||
|
||||
if ($match_comment != 1) {
|
||||
return $email1_name eq $email2_name &&
|
||||
$email1_address eq $email2_address;
|
||||
}
|
||||
return $email1_name eq $email2_name &&
|
||||
$email1_address eq $email2_address &&
|
||||
$name1_comment eq $name2_comment &&
|
||||
@ -2704,7 +2775,7 @@ sub process {
|
||||
$signoff++;
|
||||
$in_commit_log = 0;
|
||||
if ($author ne '' && $authorsignoff != 1) {
|
||||
if (same_email_addresses($1, $author, 1)) {
|
||||
if (same_email_addresses($1, $author)) {
|
||||
$authorsignoff = 1;
|
||||
} else {
|
||||
my $ctx = $1;
|
||||
@ -2760,8 +2831,17 @@ sub process {
|
||||
my $ucfirst_sign_off = ucfirst(lc($sign_off));
|
||||
|
||||
if ($sign_off !~ /$signature_tags/) {
|
||||
WARN("BAD_SIGN_OFF",
|
||||
"Non-standard signature: $sign_off\n" . $herecurr);
|
||||
my $suggested_signature = find_standard_signature($sign_off);
|
||||
if ($suggested_signature eq "") {
|
||||
WARN("BAD_SIGN_OFF",
|
||||
"Non-standard signature: $sign_off\n" . $herecurr);
|
||||
} else {
|
||||
if (WARN("BAD_SIGN_OFF",
|
||||
"Non-standard signature: '$sign_off' - perhaps '$suggested_signature'?\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/$sign_off/$suggested_signature/;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (defined $space_before && $space_before ne "") {
|
||||
if (WARN("BAD_SIGN_OFF",
|
||||
@ -2800,9 +2880,77 @@ sub process {
|
||||
$dequoted =~ s/" </ </;
|
||||
# Don't force email to have quotes
|
||||
# Allow just an angle bracketed address
|
||||
if (!same_email_addresses($email, $suggested_email, 0)) {
|
||||
if (!same_email_addresses($email, $suggested_email)) {
|
||||
if (WARN("BAD_SIGN_OFF",
|
||||
"email address '$email' might be better as '$suggested_email'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\Q$email\E/$suggested_email/;
|
||||
}
|
||||
}
|
||||
|
||||
# Address part shouldn't have comments
|
||||
my $stripped_address = $email_address;
|
||||
$stripped_address =~ s/\([^\(\)]*\)//g;
|
||||
if ($email_address ne $stripped_address) {
|
||||
if (WARN("BAD_SIGN_OFF",
|
||||
"address part of email should not have comments: '$email_address'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\Q$email_address\E/$stripped_address/;
|
||||
}
|
||||
}
|
||||
|
||||
# Only one name comment should be allowed
|
||||
my $comment_count = () = $name_comment =~ /\([^\)]+\)/g;
|
||||
if ($comment_count > 1) {
|
||||
WARN("BAD_SIGN_OFF",
|
||||
"email address '$email' might be better as '$suggested_email'\n" . $herecurr);
|
||||
"Use a single name comment in email: '$email'\n" . $herecurr);
|
||||
}
|
||||
|
||||
|
||||
# stable@vger.kernel.org or stable@kernel.org shouldn't
|
||||
# have an email name. In addition comments should strictly
|
||||
# begin with a #
|
||||
if ($email =~ /^.*stable\@(?:vger\.)?kernel\.org/i) {
|
||||
if (($comment ne "" && $comment !~ /^#.+/) ||
|
||||
($email_name ne "")) {
|
||||
my $cur_name = $email_name;
|
||||
my $new_comment = $comment;
|
||||
$cur_name =~ s/[a-zA-Z\s\-\"]+//g;
|
||||
|
||||
# Remove brackets enclosing comment text
|
||||
# and # from start of comments to get comment text
|
||||
$new_comment =~ s/^\((.*)\)$/$1/;
|
||||
$new_comment =~ s/^\[(.*)\]$/$1/;
|
||||
$new_comment =~ s/^[\s\#]+|\s+$//g;
|
||||
|
||||
$new_comment = trim("$new_comment $cur_name") if ($cur_name ne $new_comment);
|
||||
$new_comment = " # $new_comment" if ($new_comment ne "");
|
||||
my $new_email = "$email_address$new_comment";
|
||||
|
||||
if (WARN("BAD_STABLE_ADDRESS_STYLE",
|
||||
"Invalid email format for stable: '$email', prefer '$new_email'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
|
||||
}
|
||||
}
|
||||
} elsif ($comment ne "" && $comment !~ /^(?:#.+|\(.+\))$/) {
|
||||
my $new_comment = $comment;
|
||||
|
||||
# Extract comment text from within brackets or
|
||||
# c89 style /*...*/ comments
|
||||
$new_comment =~ s/^\[(.*)\]$/$1/;
|
||||
$new_comment =~ s/^\/\*(.*)\*\/$/$1/;
|
||||
|
||||
$new_comment = trim($new_comment);
|
||||
$new_comment =~ s/^[^\w]$//; # Single lettered comment with non word character is usually a typo
|
||||
$new_comment = "($new_comment)" if ($new_comment ne "");
|
||||
my $new_email = format_email($email_name, $name_comment, $email_address, $new_comment);
|
||||
|
||||
if (WARN("BAD_SIGN_OFF",
|
||||
"Unexpected content after email: '$email', should be: '$new_email'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\Q$email\E/$new_email/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2845,8 +2993,11 @@ sub process {
|
||||
|
||||
# Check for Gerrit Change-Ids not in any patch context
|
||||
if ($realfile eq '' && !$has_patch_separator && $line =~ /^\s*change-id:/i) {
|
||||
ERROR("GERRIT_CHANGE_ID",
|
||||
"Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr);
|
||||
if (ERROR("GERRIT_CHANGE_ID",
|
||||
"Remove Gerrit Change-Id's before submitting upstream\n" . $herecurr) &&
|
||||
$fix) {
|
||||
fix_delete_line($fixlinenr, $rawline);
|
||||
}
|
||||
}
|
||||
|
||||
# Check if the commit log is in a possible stack dump
|
||||
@ -2868,8 +3019,8 @@ sub process {
|
||||
# file delta changes
|
||||
$line =~ /^\s*(?:[\w\.\-]+\/)++[\w\.\-]+:/ ||
|
||||
# filename then :
|
||||
$line =~ /^\s*(?:Fixes:|Link:)/i ||
|
||||
# A Fixes: or Link: line
|
||||
$line =~ /^\s*(?:Fixes:|Link:|$signature_tags)/i ||
|
||||
# A Fixes: or Link: line or signature tag line
|
||||
$commit_log_possible_stack_dump)) {
|
||||
WARN("COMMIT_LOG_LONG_LINE",
|
||||
"Possible unwrapped commit description (prefer a maximum 75 chars per line)\n" . $herecurr);
|
||||
@ -2882,6 +3033,15 @@ sub process {
|
||||
$commit_log_possible_stack_dump = 0;
|
||||
}
|
||||
|
||||
# Check for lines starting with a #
|
||||
if ($in_commit_log && $line =~ /^#/) {
|
||||
if (WARN("COMMIT_COMMENT_SYMBOL",
|
||||
"Commit log lines starting with '#' are dropped by git as comments\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/^/ /;
|
||||
}
|
||||
}
|
||||
|
||||
# Check for git id commit length and improperly formed commit descriptions
|
||||
if ($in_commit_log && !$commit_log_possible_stack_dump &&
|
||||
$line !~ /^\s*(?:Link|Patchwork|http|https|BugLink|base-commit):/i &&
|
||||
@ -3022,15 +3182,18 @@ sub process {
|
||||
# Check for various typo / spelling mistakes
|
||||
if (defined($misspellings) &&
|
||||
($in_commit_log || $line =~ /^(?:\+|Subject:)/i)) {
|
||||
while ($rawline =~ /(?:^|[^a-z@])($misspellings)(?:\b|$|[^a-z@])/gi) {
|
||||
while ($rawline =~ /(?:^|[^\w\-'`])($misspellings)(?:[^\w\-'`]|$)/gi) {
|
||||
my $typo = $1;
|
||||
my $blank = copy_spacing($rawline);
|
||||
my $ptr = substr($blank, 0, $-[1]) . "^" x length($typo);
|
||||
my $hereptr = "$hereline$ptr\n";
|
||||
my $typo_fix = $spelling_fix{lc($typo)};
|
||||
$typo_fix = ucfirst($typo_fix) if ($typo =~ /^[A-Z]/);
|
||||
$typo_fix = uc($typo_fix) if ($typo =~ /^[A-Z]+$/);
|
||||
my $msg_level = \&WARN;
|
||||
$msg_level = \&CHK if ($file);
|
||||
if (&{$msg_level}("TYPO_SPELLING",
|
||||
"'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $herecurr) &&
|
||||
"'$typo' may be misspelled - perhaps '$typo_fix'?\n" . $hereptr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/(^|[^A-Za-z@])($typo)($|[^A-Za-z@])/$1$typo_fix$3/;
|
||||
}
|
||||
@ -3049,20 +3212,38 @@ sub process {
|
||||
}
|
||||
|
||||
# check for repeated words separated by a single space
|
||||
if ($rawline =~ /^\+/ || $in_commit_log) {
|
||||
# avoid false positive from list command eg, '-rw-r--r-- 1 root root'
|
||||
if (($rawline =~ /^\+/ || $in_commit_log) &&
|
||||
$rawline !~ /[bcCdDlMnpPs\?-][rwxsStT-]{9}/) {
|
||||
pos($rawline) = 1 if (!$in_commit_log);
|
||||
while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) {
|
||||
|
||||
my $first = $1;
|
||||
my $second = $2;
|
||||
|
||||
my $start_pos = $-[1];
|
||||
my $end_pos = $+[2];
|
||||
if ($first =~ /(?:struct|union|enum)/) {
|
||||
pos($rawline) += length($first) + length($second) + 1;
|
||||
next;
|
||||
}
|
||||
|
||||
next if ($first ne $second);
|
||||
next if (lc($first) ne lc($second));
|
||||
next if ($first eq 'long');
|
||||
|
||||
# check for character before and after the word matches
|
||||
my $start_char = '';
|
||||
my $end_char = '';
|
||||
$start_char = substr($rawline, $start_pos - 1, 1) if ($start_pos > ($in_commit_log ? 0 : 1));
|
||||
$end_char = substr($rawline, $end_pos, 1) if ($end_pos < length($rawline));
|
||||
|
||||
next if ($start_char =~ /^\S$/);
|
||||
next if (index(" \t.,;?!", $end_char) == -1);
|
||||
|
||||
# avoid repeating hex occurrences like 'ff ff fe 09 ...'
|
||||
if ($first =~ /\b[0-9a-f]{2,}\b/i) {
|
||||
next if (!exists($allow_repeated_words{lc($first)}));
|
||||
}
|
||||
|
||||
if (WARN("REPEATED_WORD",
|
||||
"Possible repeated word: '$first'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
@ -3393,8 +3574,11 @@ sub process {
|
||||
|
||||
# check for adding lines without a newline.
|
||||
if ($line =~ /^\+/ && defined $lines[$linenr] && $lines[$linenr] =~ /^\\ No newline at end of file/) {
|
||||
WARN("MISSING_EOF_NEWLINE",
|
||||
"adding a line without newline at end of file\n" . $herecurr);
|
||||
if (WARN("MISSING_EOF_NEWLINE",
|
||||
"adding a line without newline at end of file\n" . $herecurr) &&
|
||||
$fix) {
|
||||
fix_delete_line($fixlinenr+1, "No newline at end of file");
|
||||
}
|
||||
}
|
||||
|
||||
# check we are in a valid source file C or perl if not then ignore this hunk
|
||||
@ -3428,14 +3612,28 @@ sub process {
|
||||
|
||||
# check for assignments on the start of a line
|
||||
if ($sline =~ /^\+\s+($Assignment)[^=]/) {
|
||||
CHK("ASSIGNMENT_CONTINUATIONS",
|
||||
"Assignment operator '$1' should be on the previous line\n" . $hereprev);
|
||||
my $operator = $1;
|
||||
if (CHK("ASSIGNMENT_CONTINUATIONS",
|
||||
"Assignment operator '$1' should be on the previous line\n" . $hereprev) &&
|
||||
$fix && $prevrawline =~ /^\+/) {
|
||||
# add assignment operator to the previous line, remove from current line
|
||||
$fixed[$fixlinenr - 1] .= " $operator";
|
||||
$fixed[$fixlinenr] =~ s/\Q$operator\E\s*//;
|
||||
}
|
||||
}
|
||||
|
||||
# check for && or || at the start of a line
|
||||
if ($rawline =~ /^\+\s*(&&|\|\|)/) {
|
||||
CHK("LOGICAL_CONTINUATIONS",
|
||||
"Logical continuations should be on the previous line\n" . $hereprev);
|
||||
my $operator = $1;
|
||||
if (CHK("LOGICAL_CONTINUATIONS",
|
||||
"Logical continuations should be on the previous line\n" . $hereprev) &&
|
||||
$fix && $prevrawline =~ /^\+/) {
|
||||
# insert logical operator at last non-comment, non-whitepsace char on previous line
|
||||
$prevline =~ /[\s$;]*$/;
|
||||
my $line_end = substr($prevrawline, $-[0]);
|
||||
$fixed[$fixlinenr - 1] =~ s/\Q$line_end\E$/ $operator$line_end/;
|
||||
$fixed[$fixlinenr] =~ s/\Q$operator\E\s*//;
|
||||
}
|
||||
}
|
||||
|
||||
# check indentation starts on a tab stop
|
||||
@ -3674,12 +3872,16 @@ sub process {
|
||||
}
|
||||
|
||||
# check indentation of a line with a break;
|
||||
# if the previous line is a goto or return and is indented the same # of tabs
|
||||
# if the previous line is a goto, return or break
|
||||
# and is indented the same # of tabs
|
||||
if ($sline =~ /^\+([\t]+)break\s*;\s*$/) {
|
||||
my $tabs = $1;
|
||||
if ($prevline =~ /^\+$tabs(?:goto|return)\b/) {
|
||||
WARN("UNNECESSARY_BREAK",
|
||||
"break is not useful after a goto or return\n" . $hereprev);
|
||||
if ($prevline =~ /^\+$tabs(goto|return|break)\b/) {
|
||||
if (WARN("UNNECESSARY_BREAK",
|
||||
"break is not useful after a $1\n" . $hereprev) &&
|
||||
$fix) {
|
||||
fix_delete_line($fixlinenr, $rawline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4207,6 +4409,18 @@ sub process {
|
||||
}
|
||||
}
|
||||
|
||||
# check for const static or static <non ptr type> const declarations
|
||||
# prefer 'static const <foo>' over 'const static <foo>' and 'static <foo> const'
|
||||
if ($sline =~ /^\+\s*const\s+static\s+($Type)\b/ ||
|
||||
$sline =~ /^\+\s*static\s+($BasicType)\s+const\b/) {
|
||||
if (WARN("STATIC_CONST",
|
||||
"Move const after static - use 'static const $1'\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\bconst\s+static\b/static const/;
|
||||
$fixed[$fixlinenr] =~ s/\bstatic\s+($BasicType)\s+const\b/static const $1/;
|
||||
}
|
||||
}
|
||||
|
||||
# check for non-global char *foo[] = {"bar", ...} declarations.
|
||||
if ($line =~ /^.\s+(?:static\s+|const\s+)?char\s+\*\s*\w+\s*\[\s*\]\s*=\s*\{/) {
|
||||
WARN("STATIC_CONST_CHAR_ARRAY",
|
||||
@ -4329,16 +4543,23 @@ sub process {
|
||||
"printk() should include KERN_<LEVEL> facility level\n" . $herecurr);
|
||||
}
|
||||
|
||||
if ($line =~ /\bprintk\s*\(\s*KERN_([A-Z]+)/) {
|
||||
my $orig = $1;
|
||||
# prefer variants of (subsystem|netdev|dev|pr)_<level> to printk(KERN_<LEVEL>
|
||||
if ($line =~ /\b(printk(_once|_ratelimited)?)\s*\(\s*KERN_([A-Z]+)/) {
|
||||
my $printk = $1;
|
||||
my $modifier = $2;
|
||||
my $orig = $3;
|
||||
$modifier = "" if (!defined($modifier));
|
||||
my $level = lc($orig);
|
||||
$level = "warn" if ($level eq "warning");
|
||||
my $level2 = $level;
|
||||
$level2 = "dbg" if ($level eq "debug");
|
||||
$level .= $modifier;
|
||||
$level2 .= $modifier;
|
||||
WARN("PREFER_PR_LEVEL",
|
||||
"Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to printk(KERN_$orig ...\n" . $herecurr);
|
||||
"Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(... to $printk(KERN_$orig ...\n" . $herecurr);
|
||||
}
|
||||
|
||||
# prefer dev_<level> to dev_printk(KERN_<LEVEL>
|
||||
if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
|
||||
my $orig = $1;
|
||||
my $level = lc($orig);
|
||||
@ -4384,7 +4605,7 @@ sub process {
|
||||
$fix) {
|
||||
fix_delete_line($fixlinenr, $rawline);
|
||||
my $fixed_line = $rawline;
|
||||
$fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*){(.*)$/;
|
||||
$fixed_line =~ /(^..*$Type\s*$Ident\(.*\)\s*)\{(.*)$/;
|
||||
my $line1 = $1;
|
||||
my $line2 = $2;
|
||||
fix_insert_line($fixlinenr, ltrim($line1));
|
||||
@ -4879,7 +5100,7 @@ sub process {
|
||||
## $line !~ /^.\s*$Type\s+$Ident(?:\s*=[^,{]*)?\s*,\s*$Type\s*$Ident.*/) {
|
||||
##
|
||||
## # Remove any bracketed sections to ensure we do not
|
||||
## # falsly report the parameters of functions.
|
||||
## # falsely report the parameters of functions.
|
||||
## my $ln = $line;
|
||||
## while ($ln =~ s/\([^\(\)]*\)//g) {
|
||||
## }
|
||||
@ -5295,6 +5516,8 @@ sub process {
|
||||
#CamelCase
|
||||
if ($var !~ /^$Constant$/ &&
|
||||
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
|
||||
#Ignore some autogenerated defines and enum values
|
||||
$var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
|
||||
#Ignore Page<foo> variants
|
||||
$var !~ /^(?:Clear|Set|TestClear|TestSet|)Page[A-Z]/ &&
|
||||
#Ignore SI style variants like nS, mV and dB
|
||||
@ -5898,6 +6121,28 @@ sub process {
|
||||
"Avoid logging continuation uses where feasible\n" . $herecurr);
|
||||
}
|
||||
|
||||
# check for unnecessary use of %h[xudi] and %hh[xudi] in logging functions
|
||||
if (defined $stat &&
|
||||
$line =~ /\b$logFunctions\s*\(/ &&
|
||||
index($stat, '"') >= 0) {
|
||||
my $lc = $stat =~ tr@\n@@;
|
||||
$lc = $lc + $linenr;
|
||||
my $stat_real = get_stat_real($linenr, $lc);
|
||||
pos($stat_real) = index($stat_real, '"');
|
||||
while ($stat_real =~ /[^\"%]*(%[\#\d\.\*\-]*(h+)[idux])/g) {
|
||||
my $pspec = $1;
|
||||
my $h = $2;
|
||||
my $lineoff = substr($stat_real, 0, $-[1]) =~ tr@\n@@;
|
||||
if (WARN("UNNECESSARY_MODIFIER",
|
||||
"Integer promotion: Using '$h' in '$pspec' is unnecessary\n" . "$here\n$stat_real\n") &&
|
||||
$fix && $fixed[$fixlinenr + $lineoff] =~ /^\+/) {
|
||||
my $nspec = $pspec;
|
||||
$nspec =~ s/h//g;
|
||||
$fixed[$fixlinenr + $lineoff] =~ s/\Q$pspec\E/$nspec/;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# check for mask then right shift without a parentheses
|
||||
if ($perl_version_ok &&
|
||||
$line =~ /$LvalOrFunc\s*\&\s*($LvalOrFunc)\s*>>/ &&
|
||||
@ -6144,50 +6389,68 @@ sub process {
|
||||
}
|
||||
}
|
||||
|
||||
# Check for __attribute__ packed, prefer __packed
|
||||
# Check for compiler attributes
|
||||
if ($realfile !~ m@\binclude/uapi/@ &&
|
||||
$line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
|
||||
WARN("PREFER_PACKED",
|
||||
"__packed is preferred over __attribute__((packed))\n" . $herecurr);
|
||||
}
|
||||
$rawline =~ /\b__attribute__\s*\(\s*($balanced_parens)\s*\)/) {
|
||||
my $attr = $1;
|
||||
$attr =~ s/\s*\(\s*(.*)\)\s*/$1/;
|
||||
|
||||
# Check for __attribute__ aligned, prefer __aligned
|
||||
if ($realfile !~ m@\binclude/uapi/@ &&
|
||||
$line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
|
||||
WARN("PREFER_ALIGNED",
|
||||
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
|
||||
}
|
||||
my %attr_list = (
|
||||
"alias" => "__alias",
|
||||
"aligned" => "__aligned",
|
||||
"always_inline" => "__always_inline",
|
||||
"assume_aligned" => "__assume_aligned",
|
||||
"cold" => "__cold",
|
||||
"const" => "__attribute_const__",
|
||||
"copy" => "__copy",
|
||||
"designated_init" => "__designated_init",
|
||||
"externally_visible" => "__visible",
|
||||
"format" => "printf|scanf",
|
||||
"gnu_inline" => "__gnu_inline",
|
||||
"malloc" => "__malloc",
|
||||
"mode" => "__mode",
|
||||
"no_caller_saved_registers" => "__no_caller_saved_registers",
|
||||
"noclone" => "__noclone",
|
||||
"noinline" => "noinline",
|
||||
"nonstring" => "__nonstring",
|
||||
"noreturn" => "__noreturn",
|
||||
"packed" => "__packed",
|
||||
"pure" => "__pure",
|
||||
"section" => "__section",
|
||||
"used" => "__used",
|
||||
"weak" => "__weak"
|
||||
);
|
||||
|
||||
# Check for __attribute__ section, prefer __section
|
||||
if ($realfile !~ m@\binclude/uapi/@ &&
|
||||
$line =~ /\b__attribute__\s*\(\s*\(.*_*section_*\s*\(\s*("[^"]*")/) {
|
||||
my $old = substr($rawline, $-[1], $+[1] - $-[1]);
|
||||
my $new = substr($old, 1, -1);
|
||||
if (WARN("PREFER_SECTION",
|
||||
"__section($new) is preferred over __attribute__((section($old)))\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*_*section_*\s*\(\s*\Q$old\E\s*\)\s*\)\s*\)/__section($new)/;
|
||||
while ($attr =~ /\s*(\w+)\s*(${balanced_parens})?/g) {
|
||||
my $orig_attr = $1;
|
||||
my $params = '';
|
||||
$params = $2 if defined($2);
|
||||
my $curr_attr = $orig_attr;
|
||||
$curr_attr =~ s/^[\s_]+|[\s_]+$//g;
|
||||
if (exists($attr_list{$curr_attr})) {
|
||||
my $new = $attr_list{$curr_attr};
|
||||
if ($curr_attr eq "format" && $params) {
|
||||
$params =~ /^\s*\(\s*(\w+)\s*,\s*(.*)/;
|
||||
$new = "__$1\($2";
|
||||
} else {
|
||||
$new = "$new$params";
|
||||
}
|
||||
if (WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",
|
||||
"Prefer $new over __attribute__(($orig_attr$params))\n" . $herecurr) &&
|
||||
$fix) {
|
||||
my $remove = "\Q$orig_attr\E" . '\s*' . "\Q$params\E" . '(?:\s*,\s*)?';
|
||||
$fixed[$fixlinenr] =~ s/$remove//;
|
||||
$fixed[$fixlinenr] =~ s/\b__attribute__/$new __attribute__/;
|
||||
$fixed[$fixlinenr] =~ s/\}\Q$new\E/} $new/;
|
||||
$fixed[$fixlinenr] =~ s/ __attribute__\s*\(\s*\(\s*\)\s*\)//;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Check for __attribute__ format(printf, prefer __printf
|
||||
if ($realfile !~ m@\binclude/uapi/@ &&
|
||||
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
|
||||
if (WARN("PREFER_PRINTF",
|
||||
"__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf\s*,\s*(.*)\)\s*\)\s*\)/"__printf(" . trim($1) . ")"/ex;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
# Check for __attribute__ format(scanf, prefer __scanf
|
||||
if ($realfile !~ m@\binclude/uapi/@ &&
|
||||
$line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
|
||||
if (WARN("PREFER_SCANF",
|
||||
"__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
|
||||
$fix) {
|
||||
$fixed[$fixlinenr] =~ s/\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\s*,\s*(.*)\)\s*\)\s*\)/"__scanf(" . trim($1) . ")"/ex;
|
||||
# Check for __attribute__ unused, prefer __always_unused or __maybe_unused
|
||||
if ($attr =~ /^_*unused/) {
|
||||
WARN("PREFER_DEFINED_ATTRIBUTE_MACRO",
|
||||
"__always_unused or __maybe_unused is preferred over __attribute__((__unused__))\n" . $herecurr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -6968,7 +7231,7 @@ sub process {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
# This is not a patch, and we are are in 'no-patch' mode so
|
||||
# This is not a patch, and we are in 'no-patch' mode so
|
||||
# just keep quiet.
|
||||
if (!$chk_patch && !$is_patch) {
|
||||
exit(0);
|
||||
|
@ -2046,9 +2046,6 @@ fail2:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
#define list_entry_is_head(pos, head, member) (&pos->member == (head))
|
||||
|
||||
/**
|
||||
* __next_ns - find the next namespace to list
|
||||
* @root: root namespace to stop search at (NOT NULL)
|
||||
|
@ -68,3 +68,4 @@ USERCOPY_STACK_BEYOND
|
||||
USERCOPY_KERNEL
|
||||
STACKLEAK_ERASING OK: the rest of the thread stack is properly erased
|
||||
CFI_FORWARD_PROTO
|
||||
FORTIFIED_STRSCPY
|
||||
|
Loading…
Reference in New Issue
Block a user