mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-28 02:32:09 -04:00
Merge tag 'ASB-2024-11-05_11-5.4' of https://android.googlesource.com/kernel/common into android13-5.4-lahaina
https://source.android.com/docs/security/bulletin/2024-11-01 CVE-2024-36978 CVE-2024-46740 * tag 'ASB-2024-11-05_11-5.4' of https://android.googlesource.com/kernel/common: (126 commits) UPSTREAM: unicode: Don't special case ignorable code points ANDROID: 16K: Fixup padding vm_flags bits on VMA splits ANDROID: 16K: Introduce pgsize_migration_inline.h Revert "clocksource/drivers/timer-of: Remove percpu irq related code" Linux 5.4.284 Revert "parisc: Use irq_enter_rcu() to fix warning at kernel/context_tracking.c:367" cx82310_eth: fix error return code in cx82310_bind() net, sunrpc: Remap EPERM in case of connection failure in xs_tcp_setup_socket rtmutex: Drop rt_mutex::wait_lock before scheduling drm/i915/fence: Mark debug_fence_free() with __maybe_unused drm/i915/fence: Mark debug_fence_init_onstack() with __maybe_unused nvmet-tcp: fix kernel crash if commands allocation fails arm64: acpi: Harden get_cpu_for_acpi_id() against missing CPU entry arm64: acpi: Move get_cpu_for_acpi_id() to a header ACPI: processor: Fix memory leaks in error paths of processor_add() ACPI: processor: Return an error if acpi_processor_get_info() fails in processor_add() nilfs2: protect references to superblock parameters exposed in sysfs nilfs2: replace snprintf in show functions with sysfs_emit tracing: Avoid possible softlockup in tracing_iter_reset() ring-buffer: Rename ring_buffer_read() to read_buffer_iter_advance() ... Conflicts: fs/userfaultfd.c mm/madvise.c Change-Id: I9e0e9c01dd313ea38070f0077983b5e107fb6a0b
This commit is contained in:
commit
d72549f3a1
123 changed files with 4312 additions and 3860 deletions
|
|
@ -75,8 +75,9 @@ static inline unsigned long hold_time(const struct net_bridge *br)
|
|||
static inline int has_expired(const struct net_bridge *br,
|
||||
const struct net_bridge_fdb_entry *fdb)
|
||||
{
|
||||
return !fdb->is_static && !fdb->added_by_external_learn &&
|
||||
time_before_eq(fdb->updated + hold_time(br), jiffies);
|
||||
return !test_bit(BR_FDB_STATIC, &fdb->flags) &&
|
||||
!test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags) &&
|
||||
time_before_eq(fdb->updated + hold_time(br), jiffies);
|
||||
}
|
||||
|
||||
static void fdb_rcu_free(struct rcu_head *head)
|
||||
|
|
@ -201,7 +202,7 @@ static void fdb_delete(struct net_bridge *br, struct net_bridge_fdb_entry *f,
|
|||
{
|
||||
trace_fdb_delete(br, f);
|
||||
|
||||
if (f->is_static)
|
||||
if (test_bit(BR_FDB_STATIC, &f->flags))
|
||||
fdb_del_hw_addr(br, f->key.addr.addr);
|
||||
|
||||
hlist_del_init_rcu(&f->fdb_node);
|
||||
|
|
@ -228,7 +229,7 @@ static void fdb_delete_local(struct net_bridge *br,
|
|||
if (op != p && ether_addr_equal(op->dev->dev_addr, addr) &&
|
||||
(!vid || br_vlan_find(vg, vid))) {
|
||||
f->dst = op;
|
||||
f->added_by_user = 0;
|
||||
clear_bit(BR_FDB_ADDED_BY_USER, &f->flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -239,7 +240,7 @@ static void fdb_delete_local(struct net_bridge *br,
|
|||
if (p && ether_addr_equal(br->dev->dev_addr, addr) &&
|
||||
(!vid || (v && br_vlan_should_use(v)))) {
|
||||
f->dst = NULL;
|
||||
f->added_by_user = 0;
|
||||
clear_bit(BR_FDB_ADDED_BY_USER, &f->flags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -254,7 +255,8 @@ void br_fdb_find_delete_local(struct net_bridge *br,
|
|||
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
f = br_fdb_find(br, addr, vid);
|
||||
if (f && f->is_local && !f->added_by_user && f->dst == p)
|
||||
if (f && test_bit(BR_FDB_LOCAL, &f->flags) &&
|
||||
!test_bit(BR_FDB_ADDED_BY_USER, &f->flags) && f->dst == p)
|
||||
fdb_delete_local(br, p, f);
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
}
|
||||
|
|
@ -269,7 +271,8 @@ void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr)
|
|||
spin_lock_bh(&br->hash_lock);
|
||||
vg = nbp_vlan_group(p);
|
||||
hlist_for_each_entry(f, &br->fdb_list, fdb_node) {
|
||||
if (f->dst == p && f->is_local && !f->added_by_user) {
|
||||
if (f->dst == p && test_bit(BR_FDB_LOCAL, &f->flags) &&
|
||||
!test_bit(BR_FDB_ADDED_BY_USER, &f->flags)) {
|
||||
/* delete old one */
|
||||
fdb_delete_local(br, p, f);
|
||||
|
||||
|
|
@ -310,7 +313,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
|
|||
|
||||
/* If old entry was unassociated with any port, then delete it. */
|
||||
f = br_fdb_find(br, br->dev->dev_addr, 0);
|
||||
if (f && f->is_local && !f->dst && !f->added_by_user)
|
||||
if (f && test_bit(BR_FDB_LOCAL, &f->flags) &&
|
||||
!f->dst && !test_bit(BR_FDB_ADDED_BY_USER, &f->flags))
|
||||
fdb_delete_local(br, NULL, f);
|
||||
|
||||
fdb_insert(br, NULL, newaddr, 0);
|
||||
|
|
@ -325,7 +329,8 @@ void br_fdb_change_mac_address(struct net_bridge *br, const u8 *newaddr)
|
|||
if (!br_vlan_should_use(v))
|
||||
continue;
|
||||
f = br_fdb_find(br, br->dev->dev_addr, v->vid);
|
||||
if (f && f->is_local && !f->dst && !f->added_by_user)
|
||||
if (f && test_bit(BR_FDB_LOCAL, &f->flags) &&
|
||||
!f->dst && !test_bit(BR_FDB_ADDED_BY_USER, &f->flags))
|
||||
fdb_delete_local(br, NULL, f);
|
||||
fdb_insert(br, NULL, newaddr, v->vid);
|
||||
}
|
||||
|
|
@ -350,7 +355,8 @@ void br_fdb_cleanup(struct work_struct *work)
|
|||
hlist_for_each_entry_rcu(f, &br->fdb_list, fdb_node) {
|
||||
unsigned long this_timer;
|
||||
|
||||
if (f->is_static || f->added_by_external_learn)
|
||||
if (test_bit(BR_FDB_STATIC, &f->flags) ||
|
||||
test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &f->flags))
|
||||
continue;
|
||||
this_timer = f->updated + delay;
|
||||
if (time_after(this_timer, now)) {
|
||||
|
|
@ -377,7 +383,7 @@ void br_fdb_flush(struct net_bridge *br)
|
|||
|
||||
spin_lock_bh(&br->hash_lock);
|
||||
hlist_for_each_entry_safe(f, tmp, &br->fdb_list, fdb_node) {
|
||||
if (!f->is_static)
|
||||
if (!test_bit(BR_FDB_STATIC, &f->flags))
|
||||
fdb_delete(br, f, true);
|
||||
}
|
||||
spin_unlock_bh(&br->hash_lock);
|
||||
|
|
@ -401,10 +407,11 @@ void br_fdb_delete_by_port(struct net_bridge *br,
|
|||
continue;
|
||||
|
||||
if (!do_all)
|
||||
if (f->is_static || (vid && f->key.vlan_id != vid))
|
||||
if (test_bit(BR_FDB_STATIC, &f->flags) ||
|
||||
(vid && f->key.vlan_id != vid))
|
||||
continue;
|
||||
|
||||
if (f->is_local)
|
||||
if (test_bit(BR_FDB_LOCAL, &f->flags))
|
||||
fdb_delete_local(br, p, f);
|
||||
else
|
||||
fdb_delete(br, f, true);
|
||||
|
|
@ -473,8 +480,8 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf,
|
|||
fe->port_no = f->dst->port_no;
|
||||
fe->port_hi = f->dst->port_no >> 8;
|
||||
|
||||
fe->is_local = f->is_local;
|
||||
if (!f->is_static)
|
||||
fe->is_local = test_bit(BR_FDB_LOCAL, &f->flags);
|
||||
if (!test_bit(BR_FDB_STATIC, &f->flags))
|
||||
fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated);
|
||||
++fe;
|
||||
++num;
|
||||
|
|
@ -498,12 +505,12 @@ static struct net_bridge_fdb_entry *fdb_create(struct net_bridge *br,
|
|||
memcpy(fdb->key.addr.addr, addr, ETH_ALEN);
|
||||
fdb->dst = source;
|
||||
fdb->key.vlan_id = vid;
|
||||
fdb->is_local = is_local;
|
||||
fdb->is_static = is_static;
|
||||
fdb->added_by_user = 0;
|
||||
fdb->added_by_external_learn = 0;
|
||||
fdb->flags = 0;
|
||||
if (is_local)
|
||||
set_bit(BR_FDB_LOCAL, &fdb->flags);
|
||||
if (is_static)
|
||||
set_bit(BR_FDB_STATIC, &fdb->flags);
|
||||
fdb->offloaded = 0;
|
||||
fdb->is_sticky = 0;
|
||||
fdb->updated = fdb->used = jiffies;
|
||||
if (rhashtable_lookup_insert_fast(&br->fdb_hash_tbl,
|
||||
&fdb->rhnode,
|
||||
|
|
@ -530,7 +537,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
|
|||
/* it is okay to have multiple ports with same
|
||||
* address, just use the first one.
|
||||
*/
|
||||
if (fdb->is_local)
|
||||
if (test_bit(BR_FDB_LOCAL, &fdb->flags))
|
||||
return 0;
|
||||
br_warn(br, "adding interface %s with same address as a received packet (addr:%pM, vlan:%u)\n",
|
||||
source ? source->dev->name : br->dev->name, addr, vid);
|
||||
|
|
@ -576,7 +583,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
|||
fdb = fdb_find_rcu(&br->fdb_hash_tbl, addr, vid);
|
||||
if (likely(fdb)) {
|
||||
/* attempt to update an entry for a local interface */
|
||||
if (unlikely(fdb->is_local)) {
|
||||
if (unlikely(test_bit(BR_FDB_LOCAL, &fdb->flags))) {
|
||||
if (net_ratelimit())
|
||||
br_warn(br, "received packet on %s with own address as source address (addr:%pM, vlan:%u)\n",
|
||||
source->dev->name, addr, vid);
|
||||
|
|
@ -584,17 +591,18 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
|||
unsigned long now = jiffies;
|
||||
|
||||
/* fastpath: update of existing entry */
|
||||
if (unlikely(source != fdb->dst && !fdb->is_sticky)) {
|
||||
if (unlikely(source != fdb->dst &&
|
||||
!test_bit(BR_FDB_STICKY, &fdb->flags))) {
|
||||
fdb->dst = source;
|
||||
fdb_modified = true;
|
||||
/* Take over HW learned entry */
|
||||
if (unlikely(fdb->added_by_external_learn))
|
||||
fdb->added_by_external_learn = 0;
|
||||
test_and_clear_bit(BR_FDB_ADDED_BY_EXT_LEARN,
|
||||
&fdb->flags);
|
||||
}
|
||||
if (now != fdb->updated)
|
||||
fdb->updated = now;
|
||||
if (unlikely(added_by_user))
|
||||
fdb->added_by_user = 1;
|
||||
set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
|
||||
if (unlikely(fdb_modified)) {
|
||||
trace_br_fdb_update(br, source, addr, vid, added_by_user);
|
||||
fdb_notify(br, fdb, RTM_NEWNEIGH, true);
|
||||
|
|
@ -605,7 +613,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
|||
fdb = fdb_create(br, source, addr, vid, 0, 0);
|
||||
if (fdb) {
|
||||
if (unlikely(added_by_user))
|
||||
fdb->added_by_user = 1;
|
||||
set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
|
||||
trace_br_fdb_update(br, source, addr, vid,
|
||||
added_by_user);
|
||||
fdb_notify(br, fdb, RTM_NEWNEIGH, true);
|
||||
|
|
@ -620,9 +628,9 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source,
|
|||
static int fdb_to_nud(const struct net_bridge *br,
|
||||
const struct net_bridge_fdb_entry *fdb)
|
||||
{
|
||||
if (fdb->is_local)
|
||||
if (test_bit(BR_FDB_LOCAL, &fdb->flags))
|
||||
return NUD_PERMANENT;
|
||||
else if (fdb->is_static)
|
||||
else if (test_bit(BR_FDB_STATIC, &fdb->flags))
|
||||
return NUD_NOARP;
|
||||
else if (has_expired(br, fdb))
|
||||
return NUD_STALE;
|
||||
|
|
@ -654,9 +662,9 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br,
|
|||
|
||||
if (fdb->offloaded)
|
||||
ndm->ndm_flags |= NTF_OFFLOADED;
|
||||
if (fdb->added_by_external_learn)
|
||||
if (test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags))
|
||||
ndm->ndm_flags |= NTF_EXT_LEARNED;
|
||||
if (fdb->is_sticky)
|
||||
if (test_bit(BR_FDB_STICKY, &fdb->flags))
|
||||
ndm->ndm_flags |= NTF_STICKY;
|
||||
|
||||
if (nla_put(skb, NDA_LLADDR, ETH_ALEN, &fdb->key.addr))
|
||||
|
|
@ -806,7 +814,7 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
|
|||
const u8 *addr, u16 state, u16 flags, u16 vid,
|
||||
u8 ndm_flags)
|
||||
{
|
||||
u8 is_sticky = !!(ndm_flags & NTF_STICKY);
|
||||
bool is_sticky = !!(ndm_flags & NTF_STICKY);
|
||||
struct net_bridge_fdb_entry *fdb;
|
||||
bool modified = false;
|
||||
|
||||
|
|
@ -847,34 +855,28 @@ static int fdb_add_entry(struct net_bridge *br, struct net_bridge_port *source,
|
|||
|
||||
if (fdb_to_nud(br, fdb) != state) {
|
||||
if (state & NUD_PERMANENT) {
|
||||
fdb->is_local = 1;
|
||||
if (!fdb->is_static) {
|
||||
fdb->is_static = 1;
|
||||
set_bit(BR_FDB_LOCAL, &fdb->flags);
|
||||
if (!test_and_set_bit(BR_FDB_STATIC, &fdb->flags))
|
||||
fdb_add_hw_addr(br, addr);
|
||||
}
|
||||
} else if (state & NUD_NOARP) {
|
||||
fdb->is_local = 0;
|
||||
if (!fdb->is_static) {
|
||||
fdb->is_static = 1;
|
||||
clear_bit(BR_FDB_LOCAL, &fdb->flags);
|
||||
if (!test_and_set_bit(BR_FDB_STATIC, &fdb->flags))
|
||||
fdb_add_hw_addr(br, addr);
|
||||
}
|
||||
} else {
|
||||
fdb->is_local = 0;
|
||||
if (fdb->is_static) {
|
||||
fdb->is_static = 0;
|
||||
clear_bit(BR_FDB_LOCAL, &fdb->flags);
|
||||
if (test_and_clear_bit(BR_FDB_STATIC, &fdb->flags))
|
||||
fdb_del_hw_addr(br, addr);
|
||||
}
|
||||
}
|
||||
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (is_sticky != fdb->is_sticky) {
|
||||
fdb->is_sticky = is_sticky;
|
||||
if (is_sticky != test_bit(BR_FDB_STICKY, &fdb->flags)) {
|
||||
change_bit(BR_FDB_STICKY, &fdb->flags);
|
||||
modified = true;
|
||||
}
|
||||
|
||||
fdb->added_by_user = 1;
|
||||
set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
|
||||
|
||||
fdb->used = jiffies;
|
||||
if (modified) {
|
||||
|
|
@ -1071,7 +1073,7 @@ int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p)
|
|||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(f, &br->fdb_list, fdb_node) {
|
||||
/* We only care for static entries */
|
||||
if (!f->is_static)
|
||||
if (!test_bit(BR_FDB_STATIC, &f->flags))
|
||||
continue;
|
||||
err = dev_uc_add(p->dev, f->key.addr.addr);
|
||||
if (err)
|
||||
|
|
@ -1085,7 +1087,7 @@ done:
|
|||
rollback:
|
||||
hlist_for_each_entry_rcu(tmp, &br->fdb_list, fdb_node) {
|
||||
/* We only care for static entries */
|
||||
if (!tmp->is_static)
|
||||
if (!test_bit(BR_FDB_STATIC, &tmp->flags))
|
||||
continue;
|
||||
if (tmp == f)
|
||||
break;
|
||||
|
|
@ -1104,7 +1106,7 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
|
|||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(f, &br->fdb_list, fdb_node) {
|
||||
/* We only care for static entries */
|
||||
if (!f->is_static)
|
||||
if (!test_bit(BR_FDB_STATIC, &f->flags))
|
||||
continue;
|
||||
|
||||
dev_uc_del(p->dev, f->key.addr.addr);
|
||||
|
|
@ -1132,8 +1134,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
|
|||
goto err_unlock;
|
||||
}
|
||||
if (swdev_notify)
|
||||
fdb->added_by_user = 1;
|
||||
fdb->added_by_external_learn = 1;
|
||||
set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
|
||||
set_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags);
|
||||
fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
|
||||
} else {
|
||||
fdb->updated = jiffies;
|
||||
|
|
@ -1143,17 +1145,15 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
|
|||
modified = true;
|
||||
}
|
||||
|
||||
if (fdb->added_by_external_learn) {
|
||||
if (test_and_set_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags)) {
|
||||
/* Refresh entry */
|
||||
fdb->used = jiffies;
|
||||
} else if (!fdb->added_by_user) {
|
||||
/* Take over SW learned entry */
|
||||
fdb->added_by_external_learn = 1;
|
||||
} else {
|
||||
modified = true;
|
||||
}
|
||||
|
||||
if (swdev_notify)
|
||||
fdb->added_by_user = 1;
|
||||
set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
|
||||
|
||||
if (modified)
|
||||
fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
|
||||
|
|
@ -1175,7 +1175,7 @@ int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
|
|||
spin_lock_bh(&br->hash_lock);
|
||||
|
||||
fdb = br_fdb_find(br, addr, vid);
|
||||
if (fdb && fdb->added_by_external_learn)
|
||||
if (fdb && test_bit(BR_FDB_ADDED_BY_EXT_LEARN, &fdb->flags))
|
||||
fdb_delete(br, fdb, swdev_notify);
|
||||
else
|
||||
err = -ENOENT;
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
|
|||
if (dst) {
|
||||
unsigned long now = jiffies;
|
||||
|
||||
if (dst->is_local)
|
||||
if (test_bit(BR_FDB_LOCAL, &dst->flags))
|
||||
return br_pass_frame_up(skb);
|
||||
|
||||
if (now != dst->used)
|
||||
|
|
|
|||
|
|
@ -175,6 +175,15 @@ struct net_bridge_vlan_group {
|
|||
u16 pvid;
|
||||
};
|
||||
|
||||
/* bridge fdb flags */
|
||||
enum {
|
||||
BR_FDB_LOCAL,
|
||||
BR_FDB_STATIC,
|
||||
BR_FDB_STICKY,
|
||||
BR_FDB_ADDED_BY_USER,
|
||||
BR_FDB_ADDED_BY_EXT_LEARN,
|
||||
};
|
||||
|
||||
struct net_bridge_fdb_key {
|
||||
mac_addr addr;
|
||||
u16 vlan_id;
|
||||
|
|
@ -186,12 +195,8 @@ struct net_bridge_fdb_entry {
|
|||
|
||||
struct net_bridge_fdb_key key;
|
||||
struct hlist_node fdb_node;
|
||||
unsigned char is_local:1,
|
||||
is_static:1,
|
||||
is_sticky:1,
|
||||
added_by_user:1,
|
||||
added_by_external_learn:1,
|
||||
offloaded:1;
|
||||
unsigned long flags;
|
||||
unsigned char offloaded:1;
|
||||
|
||||
/* write-heavy members should not affect lookups */
|
||||
unsigned long updated ____cacheline_aligned_in_smp;
|
||||
|
|
|
|||
|
|
@ -129,14 +129,16 @@ br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
|
|||
br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr,
|
||||
fdb->key.vlan_id,
|
||||
fdb->dst->dev,
|
||||
fdb->added_by_user,
|
||||
test_bit(BR_FDB_ADDED_BY_USER,
|
||||
&fdb->flags),
|
||||
fdb->offloaded);
|
||||
break;
|
||||
case RTM_NEWNEIGH:
|
||||
br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr,
|
||||
fdb->key.vlan_id,
|
||||
fdb->dst->dev,
|
||||
fdb->added_by_user,
|
||||
test_bit(BR_FDB_ADDED_BY_USER,
|
||||
&fdb->flags),
|
||||
fdb->offloaded);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue