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:
Linus Torvalds 2020-12-15 23:26:37 -08:00
commit f986e35083
87 changed files with 1566 additions and 722 deletions

View 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.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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);
}

View File

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

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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,
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
*/
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/math.h>
#include <linux/types.h>
/**

View File

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

View File

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

View File

@ -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().

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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