Merge tag 'ASB-2024-02-05_11-5.4' of https://android.googlesource.com/kernel/common into android13-5.4-lahaina
https://source.android.com/docs/security/bulletin/2024-02-01 * tag 'ASB-2024-02-05_11-5.4' of https://android.googlesource.com/kernel/common: Reapply "perf: Fix perf_event_validate_size()" UPSTREAM: ida: Fix crash in ida_free when the bitmap is empty UPSTREAM: netfilter: nf_tables: Reject tables of unsupported family Reapply "perf: Disallow mis-matched inherited group reads" UPSTREAM: ath10k: Get rid of "per_ce_irq" hw param UPSTREAM: ath10k: Keep track of which interrupts fired, don't poll them UPSTREAM: ath10k: Add interrupt summary based CE processing UPSTREAM: ath10k: Wait until copy complete is actually done before completing FROMGIT: clk: qcom: gcc-sdm845: Add soft dependency on rpmhpd Conflicts: kernel/events/core.c net/netfilter/nf_tables_api.c Change-Id: Id54c39eddcf408eff81a27a89621447e6b5f0e8e
This commit is contained in:
commit
a74c928fd6
165660
android/abi_gki_aarch64.xml
165660
android/abi_gki_aarch64.xml
File diff suppressed because it is too large
Load Diff
@ -608,6 +608,9 @@ struct perf_event {
|
|||||||
/* The cumulative AND of all event_caps for events in this group. */
|
/* The cumulative AND of all event_caps for events in this group. */
|
||||||
int group_caps;
|
int group_caps;
|
||||||
|
|
||||||
|
#ifndef __GENKSYMS__
|
||||||
|
unsigned int group_generation;
|
||||||
|
#endif
|
||||||
struct perf_event *group_leader;
|
struct perf_event *group_leader;
|
||||||
struct pmu *pmu;
|
struct pmu *pmu;
|
||||||
void *pmu_private;
|
void *pmu_private;
|
||||||
|
@ -1732,28 +1732,31 @@ static inline void perf_event__state_init(struct perf_event *event)
|
|||||||
PERF_EVENT_STATE_INACTIVE;
|
PERF_EVENT_STATE_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __perf_event_read_size(struct perf_event *event, int nr_siblings)
|
static int __perf_event_read_size(u64 read_format, int nr_siblings)
|
||||||
{
|
{
|
||||||
int entry = sizeof(u64); /* value */
|
int entry = sizeof(u64); /* value */
|
||||||
int size = 0;
|
int size = 0;
|
||||||
int nr = 1;
|
int nr = 1;
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_ID)
|
if (read_format & PERF_FORMAT_ID)
|
||||||
entry += sizeof(u64);
|
entry += sizeof(u64);
|
||||||
|
|
||||||
if (event->attr.read_format & PERF_FORMAT_GROUP) {
|
if (read_format & PERF_FORMAT_GROUP) {
|
||||||
nr += nr_siblings;
|
nr += nr_siblings;
|
||||||
size += sizeof(u64);
|
size += sizeof(u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
size += entry * nr;
|
/*
|
||||||
event->read_size = size;
|
* Since perf_event_validate_size() limits this to 16k and inhibits
|
||||||
|
* adding more siblings, this will never overflow.
|
||||||
|
*/
|
||||||
|
return size + nr * entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
||||||
@ -1794,8 +1797,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
|||||||
*/
|
*/
|
||||||
static void perf_event__header_size(struct perf_event *event)
|
static void perf_event__header_size(struct perf_event *event)
|
||||||
{
|
{
|
||||||
__perf_event_read_size(event,
|
event->read_size =
|
||||||
event->group_leader->nr_siblings);
|
__perf_event_read_size(event->attr.read_format,
|
||||||
|
event->group_leader->nr_siblings);
|
||||||
__perf_event_header_size(event, event->attr.sample_type);
|
__perf_event_header_size(event, event->attr.sample_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1826,24 +1830,35 @@ static void perf_event__id_header_size(struct perf_event *event)
|
|||||||
event->id_header_size = size;
|
event->id_header_size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that adding an event to the group does not result in anybody
|
||||||
|
* overflowing the 64k event limit imposed by the output buffer.
|
||||||
|
*
|
||||||
|
* Specifically, check that the read_size for the event does not exceed 16k,
|
||||||
|
* read_size being the one term that grows with groups size. Since read_size
|
||||||
|
* depends on per-event read_format, also (re)check the existing events.
|
||||||
|
*
|
||||||
|
* This leaves 48k for the constant size fields and things like callchains,
|
||||||
|
* branch stacks and register sets.
|
||||||
|
*/
|
||||||
static bool perf_event_validate_size(struct perf_event *event)
|
static bool perf_event_validate_size(struct perf_event *event)
|
||||||
{
|
{
|
||||||
/*
|
struct perf_event *sibling, *group_leader = event->group_leader;
|
||||||
* The values computed here will be over-written when we actually
|
|
||||||
* attach the event.
|
|
||||||
*/
|
|
||||||
__perf_event_read_size(event, event->group_leader->nr_siblings + 1);
|
|
||||||
__perf_event_header_size(event, event->attr.sample_type & ~PERF_SAMPLE_READ);
|
|
||||||
perf_event__id_header_size(event);
|
|
||||||
|
|
||||||
/*
|
if (__perf_event_read_size(event->attr.read_format,
|
||||||
* Sum the lot; should not exceed the 64k limit we have on records.
|
group_leader->nr_siblings + 1) > 16*1024)
|
||||||
* Conservative limit to allow for callchains and other variable fields.
|
|
||||||
*/
|
|
||||||
if (event->read_size + event->header_size +
|
|
||||||
event->id_header_size + sizeof(struct perf_event_header) >= 16*1024)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (__perf_event_read_size(group_leader->attr.read_format,
|
||||||
|
group_leader->nr_siblings + 1) > 16*1024)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for_each_sibling_event(sibling, group_leader) {
|
||||||
|
if (__perf_event_read_size(sibling->attr.read_format,
|
||||||
|
group_leader->nr_siblings + 1) > 16*1024)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1870,6 +1885,7 @@ static void perf_group_attach(struct perf_event *event)
|
|||||||
|
|
||||||
list_add_tail(&event->sibling_list, &group_leader->sibling_list);
|
list_add_tail(&event->sibling_list, &group_leader->sibling_list);
|
||||||
group_leader->nr_siblings++;
|
group_leader->nr_siblings++;
|
||||||
|
group_leader->group_generation++;
|
||||||
|
|
||||||
perf_event__header_size(group_leader);
|
perf_event__header_size(group_leader);
|
||||||
|
|
||||||
@ -2025,6 +2041,7 @@ static void perf_group_detach(struct perf_event *event)
|
|||||||
if (event->group_leader != event) {
|
if (event->group_leader != event) {
|
||||||
list_del_init(&event->sibling_list);
|
list_del_init(&event->sibling_list);
|
||||||
event->group_leader->nr_siblings--;
|
event->group_leader->nr_siblings--;
|
||||||
|
event->group_leader->group_generation++;
|
||||||
#ifdef CONFIG_PERF_KERNEL_SHARE
|
#ifdef CONFIG_PERF_KERNEL_SHARE
|
||||||
if (event->shared)
|
if (event->shared)
|
||||||
event->group_leader = event;
|
event->group_leader = event;
|
||||||
@ -4925,7 +4942,7 @@ static int __perf_read_group_add(struct perf_event *leader,
|
|||||||
u64 read_format, u64 *values)
|
u64 read_format, u64 *values)
|
||||||
{
|
{
|
||||||
struct perf_event_context *ctx = leader->ctx;
|
struct perf_event_context *ctx = leader->ctx;
|
||||||
struct perf_event *sub;
|
struct perf_event *sub, *parent;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int n = 1; /* skip @nr */
|
int n = 1; /* skip @nr */
|
||||||
int ret;
|
int ret;
|
||||||
@ -4935,6 +4952,33 @@ static int __perf_read_group_add(struct perf_event *leader,
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&ctx->lock, flags);
|
raw_spin_lock_irqsave(&ctx->lock, flags);
|
||||||
|
/*
|
||||||
|
* Verify the grouping between the parent and child (inherited)
|
||||||
|
* events is still in tact.
|
||||||
|
*
|
||||||
|
* Specifically:
|
||||||
|
* - leader->ctx->lock pins leader->sibling_list
|
||||||
|
* - parent->child_mutex pins parent->child_list
|
||||||
|
* - parent->ctx->mutex pins parent->sibling_list
|
||||||
|
*
|
||||||
|
* Because parent->ctx != leader->ctx (and child_list nests inside
|
||||||
|
* ctx->mutex), group destruction is not atomic between children, also
|
||||||
|
* see perf_event_release_kernel(). Additionally, parent can grow the
|
||||||
|
* group.
|
||||||
|
*
|
||||||
|
* Therefore it is possible to have parent and child groups in a
|
||||||
|
* different configuration and summing over such a beast makes no sense
|
||||||
|
* what so ever.
|
||||||
|
*
|
||||||
|
* Reject this.
|
||||||
|
*/
|
||||||
|
parent = leader->parent;
|
||||||
|
if (parent &&
|
||||||
|
(parent->group_generation != leader->group_generation ||
|
||||||
|
parent->nr_siblings != leader->nr_siblings)) {
|
||||||
|
ret = -ECHILD;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since we co-schedule groups, {enabled,running} times of siblings
|
* Since we co-schedule groups, {enabled,running} times of siblings
|
||||||
@ -4964,8 +5008,9 @@ static int __perf_read_group_add(struct perf_event *leader,
|
|||||||
values[n++] = primary_event_id(sub);
|
values[n++] = primary_event_id(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
raw_spin_unlock_irqrestore(&ctx->lock, flags);
|
raw_spin_unlock_irqrestore(&ctx->lock, flags);
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int perf_read_group(struct perf_event *event,
|
static int perf_read_group(struct perf_event *event,
|
||||||
@ -4984,10 +5029,6 @@ static int perf_read_group(struct perf_event *event,
|
|||||||
|
|
||||||
values[0] = 1 + leader->nr_siblings;
|
values[0] = 1 + leader->nr_siblings;
|
||||||
|
|
||||||
/*
|
|
||||||
* By locking the child_mutex of the leader we effectively
|
|
||||||
* lock the child list of all siblings.. XXX explain how.
|
|
||||||
*/
|
|
||||||
mutex_lock(&leader->child_mutex);
|
mutex_lock(&leader->child_mutex);
|
||||||
|
|
||||||
ret = __perf_read_group_add(leader, read_format, values);
|
ret = __perf_read_group_add(leader, read_format, values);
|
||||||
@ -12288,6 +12329,7 @@ static int inherit_group(struct perf_event *parent_event,
|
|||||||
!perf_get_aux_event(child_ctr, leader))
|
!perf_get_aux_event(child_ctr, leader))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
leader->group_generation = parent_event->group_generation;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7117,14 +7117,9 @@ struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,
|
|||||||
if (!trans)
|
if (!trans)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
trans->net = maybe_get_net(net);
|
|
||||||
if (!trans->net) {
|
|
||||||
kfree(trans);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
refcount_inc(&set->refs);
|
refcount_inc(&set->refs);
|
||||||
trans->set = set;
|
trans->set = set;
|
||||||
|
trans->net = get_net(net);
|
||||||
trans->seq = gc_seq;
|
trans->seq = gc_seq;
|
||||||
|
|
||||||
return trans;
|
return trans;
|
||||||
|
Loading…
Reference in New Issue
Block a user