Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Ingo writes: "x86 fixes An intel_rdt memory access fix and a VLA fix in pgd_alloc()." * 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/mm: Avoid VLA in pgd_alloc() x86/intel_rdt: Fix out-of-bounds memory access in CBM tests
This commit is contained in:
commit
9f203e2f2f
|
@ -529,14 +529,14 @@ ssize_t rdtgroup_schemata_write(struct kernfs_open_file *of,
|
||||||
int rdtgroup_schemata_show(struct kernfs_open_file *of,
|
int rdtgroup_schemata_show(struct kernfs_open_file *of,
|
||||||
struct seq_file *s, void *v);
|
struct seq_file *s, void *v);
|
||||||
bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d,
|
bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d,
|
||||||
u32 _cbm, int closid, bool exclusive);
|
unsigned long cbm, int closid, bool exclusive);
|
||||||
unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r, struct rdt_domain *d,
|
unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r, struct rdt_domain *d,
|
||||||
u32 cbm);
|
unsigned long cbm);
|
||||||
enum rdtgrp_mode rdtgroup_mode_by_closid(int closid);
|
enum rdtgrp_mode rdtgroup_mode_by_closid(int closid);
|
||||||
int rdtgroup_tasks_assigned(struct rdtgroup *r);
|
int rdtgroup_tasks_assigned(struct rdtgroup *r);
|
||||||
int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
|
int rdtgroup_locksetup_enter(struct rdtgroup *rdtgrp);
|
||||||
int rdtgroup_locksetup_exit(struct rdtgroup *rdtgrp);
|
int rdtgroup_locksetup_exit(struct rdtgroup *rdtgrp);
|
||||||
bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_domain *d, u32 _cbm);
|
bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_domain *d, unsigned long cbm);
|
||||||
bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d);
|
bool rdtgroup_pseudo_locked_in_hierarchy(struct rdt_domain *d);
|
||||||
int rdt_pseudo_lock_init(void);
|
int rdt_pseudo_lock_init(void);
|
||||||
void rdt_pseudo_lock_release(void);
|
void rdt_pseudo_lock_release(void);
|
||||||
|
|
|
@ -797,25 +797,27 @@ int rdtgroup_locksetup_exit(struct rdtgroup *rdtgrp)
|
||||||
/**
|
/**
|
||||||
* rdtgroup_cbm_overlaps_pseudo_locked - Test if CBM or portion is pseudo-locked
|
* rdtgroup_cbm_overlaps_pseudo_locked - Test if CBM or portion is pseudo-locked
|
||||||
* @d: RDT domain
|
* @d: RDT domain
|
||||||
* @_cbm: CBM to test
|
* @cbm: CBM to test
|
||||||
*
|
*
|
||||||
* @d represents a cache instance and @_cbm a capacity bitmask that is
|
* @d represents a cache instance and @cbm a capacity bitmask that is
|
||||||
* considered for it. Determine if @_cbm overlaps with any existing
|
* considered for it. Determine if @cbm overlaps with any existing
|
||||||
* pseudo-locked region on @d.
|
* pseudo-locked region on @d.
|
||||||
*
|
*
|
||||||
* Return: true if @_cbm overlaps with pseudo-locked region on @d, false
|
* @cbm is unsigned long, even if only 32 bits are used, to make the
|
||||||
|
* bitmap functions work correctly.
|
||||||
|
*
|
||||||
|
* Return: true if @cbm overlaps with pseudo-locked region on @d, false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_domain *d, u32 _cbm)
|
bool rdtgroup_cbm_overlaps_pseudo_locked(struct rdt_domain *d, unsigned long cbm)
|
||||||
{
|
{
|
||||||
unsigned long *cbm = (unsigned long *)&_cbm;
|
|
||||||
unsigned long *cbm_b;
|
|
||||||
unsigned int cbm_len;
|
unsigned int cbm_len;
|
||||||
|
unsigned long cbm_b;
|
||||||
|
|
||||||
if (d->plr) {
|
if (d->plr) {
|
||||||
cbm_len = d->plr->r->cache.cbm_len;
|
cbm_len = d->plr->r->cache.cbm_len;
|
||||||
cbm_b = (unsigned long *)&d->plr->cbm;
|
cbm_b = d->plr->cbm;
|
||||||
if (bitmap_intersects(cbm, cbm_b, cbm_len))
|
if (bitmap_intersects(&cbm, &cbm_b, cbm_len))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -975,33 +975,34 @@ static int rdtgroup_mode_show(struct kernfs_open_file *of,
|
||||||
* is false then overlaps with any resource group or hardware entities
|
* is false then overlaps with any resource group or hardware entities
|
||||||
* will be considered.
|
* will be considered.
|
||||||
*
|
*
|
||||||
|
* @cbm is unsigned long, even if only 32 bits are used, to make the
|
||||||
|
* bitmap functions work correctly.
|
||||||
|
*
|
||||||
* Return: false if CBM does not overlap, true if it does.
|
* Return: false if CBM does not overlap, true if it does.
|
||||||
*/
|
*/
|
||||||
bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d,
|
bool rdtgroup_cbm_overlaps(struct rdt_resource *r, struct rdt_domain *d,
|
||||||
u32 _cbm, int closid, bool exclusive)
|
unsigned long cbm, int closid, bool exclusive)
|
||||||
{
|
{
|
||||||
unsigned long *cbm = (unsigned long *)&_cbm;
|
|
||||||
unsigned long *ctrl_b;
|
|
||||||
enum rdtgrp_mode mode;
|
enum rdtgrp_mode mode;
|
||||||
|
unsigned long ctrl_b;
|
||||||
u32 *ctrl;
|
u32 *ctrl;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Check for any overlap with regions used by hardware directly */
|
/* Check for any overlap with regions used by hardware directly */
|
||||||
if (!exclusive) {
|
if (!exclusive) {
|
||||||
if (bitmap_intersects(cbm,
|
ctrl_b = r->cache.shareable_bits;
|
||||||
(unsigned long *)&r->cache.shareable_bits,
|
if (bitmap_intersects(&cbm, &ctrl_b, r->cache.cbm_len))
|
||||||
r->cache.cbm_len))
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for overlap with other resource groups */
|
/* Check for overlap with other resource groups */
|
||||||
ctrl = d->ctrl_val;
|
ctrl = d->ctrl_val;
|
||||||
for (i = 0; i < closids_supported(); i++, ctrl++) {
|
for (i = 0; i < closids_supported(); i++, ctrl++) {
|
||||||
ctrl_b = (unsigned long *)ctrl;
|
ctrl_b = *ctrl;
|
||||||
mode = rdtgroup_mode_by_closid(i);
|
mode = rdtgroup_mode_by_closid(i);
|
||||||
if (closid_allocated(i) && i != closid &&
|
if (closid_allocated(i) && i != closid &&
|
||||||
mode != RDT_MODE_PSEUDO_LOCKSETUP) {
|
mode != RDT_MODE_PSEUDO_LOCKSETUP) {
|
||||||
if (bitmap_intersects(cbm, ctrl_b, r->cache.cbm_len)) {
|
if (bitmap_intersects(&cbm, &ctrl_b, r->cache.cbm_len)) {
|
||||||
if (exclusive) {
|
if (exclusive) {
|
||||||
if (mode == RDT_MODE_EXCLUSIVE)
|
if (mode == RDT_MODE_EXCLUSIVE)
|
||||||
return true;
|
return true;
|
||||||
|
@ -1138,15 +1139,18 @@ out:
|
||||||
* computed by first dividing the total cache size by the CBM length to
|
* computed by first dividing the total cache size by the CBM length to
|
||||||
* determine how many bytes each bit in the bitmask represents. The result
|
* determine how many bytes each bit in the bitmask represents. The result
|
||||||
* is multiplied with the number of bits set in the bitmask.
|
* is multiplied with the number of bits set in the bitmask.
|
||||||
|
*
|
||||||
|
* @cbm is unsigned long, even if only 32 bits are used to make the
|
||||||
|
* bitmap functions work correctly.
|
||||||
*/
|
*/
|
||||||
unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r,
|
unsigned int rdtgroup_cbm_to_size(struct rdt_resource *r,
|
||||||
struct rdt_domain *d, u32 cbm)
|
struct rdt_domain *d, unsigned long cbm)
|
||||||
{
|
{
|
||||||
struct cpu_cacheinfo *ci;
|
struct cpu_cacheinfo *ci;
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
int num_b, i;
|
int num_b, i;
|
||||||
|
|
||||||
num_b = bitmap_weight((unsigned long *)&cbm, r->cache.cbm_len);
|
num_b = bitmap_weight(&cbm, r->cache.cbm_len);
|
||||||
ci = get_cpu_cacheinfo(cpumask_any(&d->cpu_mask));
|
ci = get_cpu_cacheinfo(cpumask_any(&d->cpu_mask));
|
||||||
for (i = 0; i < ci->num_leaves; i++) {
|
for (i = 0; i < ci->num_leaves; i++) {
|
||||||
if (ci->info_list[i].level == r->cache_level) {
|
if (ci->info_list[i].level == r->cache_level) {
|
||||||
|
@ -2353,6 +2357,7 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
|
||||||
u32 used_b = 0, unused_b = 0;
|
u32 used_b = 0, unused_b = 0;
|
||||||
u32 closid = rdtgrp->closid;
|
u32 closid = rdtgrp->closid;
|
||||||
struct rdt_resource *r;
|
struct rdt_resource *r;
|
||||||
|
unsigned long tmp_cbm;
|
||||||
enum rdtgrp_mode mode;
|
enum rdtgrp_mode mode;
|
||||||
struct rdt_domain *d;
|
struct rdt_domain *d;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
@ -2390,9 +2395,14 @@ static int rdtgroup_init_alloc(struct rdtgroup *rdtgrp)
|
||||||
* modify the CBM based on system availability.
|
* modify the CBM based on system availability.
|
||||||
*/
|
*/
|
||||||
cbm_ensure_valid(&d->new_ctrl, r);
|
cbm_ensure_valid(&d->new_ctrl, r);
|
||||||
if (bitmap_weight((unsigned long *) &d->new_ctrl,
|
/*
|
||||||
r->cache.cbm_len) <
|
* Assign the u32 CBM to an unsigned long to ensure
|
||||||
r->cache.min_cbm_bits) {
|
* that bitmap_weight() does not access out-of-bound
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
tmp_cbm = d->new_ctrl;
|
||||||
|
if (bitmap_weight(&tmp_cbm, r->cache.cbm_len) <
|
||||||
|
r->cache.min_cbm_bits) {
|
||||||
rdt_last_cmd_printf("no space on %s:%d\n",
|
rdt_last_cmd_printf("no space on %s:%d\n",
|
||||||
r->name, d->id);
|
r->name, d->id);
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
|
|
|
@ -115,6 +115,8 @@ static inline void pgd_list_del(pgd_t *pgd)
|
||||||
|
|
||||||
#define UNSHARED_PTRS_PER_PGD \
|
#define UNSHARED_PTRS_PER_PGD \
|
||||||
(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
|
(SHARED_KERNEL_PMD ? KERNEL_PGD_BOUNDARY : PTRS_PER_PGD)
|
||||||
|
#define MAX_UNSHARED_PTRS_PER_PGD \
|
||||||
|
max_t(size_t, KERNEL_PGD_BOUNDARY, PTRS_PER_PGD)
|
||||||
|
|
||||||
|
|
||||||
static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
|
static void pgd_set_mm(pgd_t *pgd, struct mm_struct *mm)
|
||||||
|
@ -181,6 +183,7 @@ static void pgd_dtor(pgd_t *pgd)
|
||||||
* and initialize the kernel pmds here.
|
* and initialize the kernel pmds here.
|
||||||
*/
|
*/
|
||||||
#define PREALLOCATED_PMDS UNSHARED_PTRS_PER_PGD
|
#define PREALLOCATED_PMDS UNSHARED_PTRS_PER_PGD
|
||||||
|
#define MAX_PREALLOCATED_PMDS MAX_UNSHARED_PTRS_PER_PGD
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We allocate separate PMDs for the kernel part of the user page-table
|
* We allocate separate PMDs for the kernel part of the user page-table
|
||||||
|
@ -189,6 +192,7 @@ static void pgd_dtor(pgd_t *pgd)
|
||||||
*/
|
*/
|
||||||
#define PREALLOCATED_USER_PMDS (static_cpu_has(X86_FEATURE_PTI) ? \
|
#define PREALLOCATED_USER_PMDS (static_cpu_has(X86_FEATURE_PTI) ? \
|
||||||
KERNEL_PGD_PTRS : 0)
|
KERNEL_PGD_PTRS : 0)
|
||||||
|
#define MAX_PREALLOCATED_USER_PMDS KERNEL_PGD_PTRS
|
||||||
|
|
||||||
void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
|
void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
|
||||||
{
|
{
|
||||||
|
@ -210,7 +214,9 @@ void pud_populate(struct mm_struct *mm, pud_t *pudp, pmd_t *pmd)
|
||||||
|
|
||||||
/* No need to prepopulate any pagetable entries in non-PAE modes. */
|
/* No need to prepopulate any pagetable entries in non-PAE modes. */
|
||||||
#define PREALLOCATED_PMDS 0
|
#define PREALLOCATED_PMDS 0
|
||||||
|
#define MAX_PREALLOCATED_PMDS 0
|
||||||
#define PREALLOCATED_USER_PMDS 0
|
#define PREALLOCATED_USER_PMDS 0
|
||||||
|
#define MAX_PREALLOCATED_USER_PMDS 0
|
||||||
#endif /* CONFIG_X86_PAE */
|
#endif /* CONFIG_X86_PAE */
|
||||||
|
|
||||||
static void free_pmds(struct mm_struct *mm, pmd_t *pmds[], int count)
|
static void free_pmds(struct mm_struct *mm, pmd_t *pmds[], int count)
|
||||||
|
@ -428,8 +434,8 @@ static inline void _pgd_free(pgd_t *pgd)
|
||||||
pgd_t *pgd_alloc(struct mm_struct *mm)
|
pgd_t *pgd_alloc(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
pmd_t *u_pmds[PREALLOCATED_USER_PMDS];
|
pmd_t *u_pmds[MAX_PREALLOCATED_USER_PMDS];
|
||||||
pmd_t *pmds[PREALLOCATED_PMDS];
|
pmd_t *pmds[MAX_PREALLOCATED_PMDS];
|
||||||
|
|
||||||
pgd = _pgd_alloc();
|
pgd = _pgd_alloc();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue