e2aed161fc
Commit 209d35ee34
("ipv6: fix memory leak in fib6_rule_suppress")
added a new variable to the fips_rules_ops.suppress() callback function
pointer in order to properly handle a memory leak.
This change is not a real ABI breakage, but since the function pointer
structure is included in other structures within the networking stack,
and they all propagate up to structures that are tracked, libabigail
properly detects this change.
There is no problem making the change, as the only providers of these
callback functions are in the kernel already, and have been fixed up in
this commit, and the variable size does not change (function pointers
are function pointers), so paper over the CRC change with a judicious
ifdef __GENKSYMS__ hack and update the .xml file to properly reflect the
updates change:
Leaf changes summary: 1 artifact changed
Changed leaf types summary: 1 leaf type changed
Removed/Changed/Added functions summary: 0 Removed, 0 Changed, 0 Added function
Removed/Changed/Added variables summary: 0 Removed, 0 Changed, 0 Added variable
'struct fib_rules_ops at fib_rules.h:60:1' changed:
type size hasn't changed
there are data member changes:
type 'typedef bool (fib_rule*, fib_lookup_arg*)*' of 'fib_rules_ops::suppress' changed:
pointer type changed from: 'typedef bool (fib_rule*, fib_lookup_arg*)*' to: 'typedef bool (fib_rule*, int, fib_lookup_arg*)*'
2448 impacted interfaces
Bug: 161946584
Change-Id: I5fd2fcece8f57536369c51e438bd2739631b34e3
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
234 lines
6.5 KiB
C
234 lines
6.5 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __NET_FIB_RULES_H
|
|
#define __NET_FIB_RULES_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/netdevice.h>
|
|
#include <linux/fib_rules.h>
|
|
#include <linux/refcount.h>
|
|
#include <net/flow.h>
|
|
#include <net/rtnetlink.h>
|
|
#include <net/fib_notifier.h>
|
|
#include <linux/indirect_call_wrapper.h>
|
|
|
|
struct fib_kuid_range {
|
|
kuid_t start;
|
|
kuid_t end;
|
|
};
|
|
|
|
struct fib_rule {
|
|
struct list_head list;
|
|
int iifindex;
|
|
int oifindex;
|
|
u32 mark;
|
|
u32 mark_mask;
|
|
u32 flags;
|
|
u32 table;
|
|
u8 action;
|
|
u8 l3mdev;
|
|
u8 proto;
|
|
u8 ip_proto;
|
|
u32 target;
|
|
__be64 tun_id;
|
|
struct fib_rule __rcu *ctarget;
|
|
struct net *fr_net;
|
|
|
|
refcount_t refcnt;
|
|
u32 pref;
|
|
int suppress_ifgroup;
|
|
int suppress_prefixlen;
|
|
char iifname[IFNAMSIZ];
|
|
char oifname[IFNAMSIZ];
|
|
struct fib_kuid_range uid_range;
|
|
struct fib_rule_port_range sport_range;
|
|
struct fib_rule_port_range dport_range;
|
|
struct rcu_head rcu;
|
|
};
|
|
|
|
struct fib_lookup_arg {
|
|
void *lookup_ptr;
|
|
const void *lookup_data;
|
|
void *result;
|
|
struct fib_rule *rule;
|
|
u32 table;
|
|
int flags;
|
|
#define FIB_LOOKUP_NOREF 1
|
|
#define FIB_LOOKUP_IGNORE_LINKSTATE 2
|
|
};
|
|
|
|
struct fib_rules_ops {
|
|
int family;
|
|
struct list_head list;
|
|
int rule_size;
|
|
int addr_size;
|
|
int unresolved_rules;
|
|
int nr_goto_rules;
|
|
unsigned int fib_rules_seq;
|
|
|
|
int (*action)(struct fib_rule *,
|
|
struct flowi *, int,
|
|
struct fib_lookup_arg *);
|
|
/* __GENKSYMS__ hack to preserve the abi change that happened in
|
|
* cdef485217d3 ("ipv6: fix memory leak in fib6_rule_suppress")
|
|
*/
|
|
#ifdef __GENKSYMS__
|
|
bool (*suppress)(struct fib_rule *,
|
|
#else
|
|
bool (*suppress)(struct fib_rule *, int,
|
|
#endif
|
|
struct fib_lookup_arg *);
|
|
int (*match)(struct fib_rule *,
|
|
struct flowi *, int);
|
|
int (*configure)(struct fib_rule *,
|
|
struct sk_buff *,
|
|
struct fib_rule_hdr *,
|
|
struct nlattr **,
|
|
struct netlink_ext_ack *);
|
|
int (*delete)(struct fib_rule *);
|
|
int (*compare)(struct fib_rule *,
|
|
struct fib_rule_hdr *,
|
|
struct nlattr **);
|
|
int (*fill)(struct fib_rule *, struct sk_buff *,
|
|
struct fib_rule_hdr *);
|
|
size_t (*nlmsg_payload)(struct fib_rule *);
|
|
|
|
/* Called after modifications to the rules set, must flush
|
|
* the route cache if one exists. */
|
|
void (*flush_cache)(struct fib_rules_ops *ops);
|
|
|
|
int nlgroup;
|
|
const struct nla_policy *policy;
|
|
struct list_head rules_list;
|
|
struct module *owner;
|
|
struct net *fro_net;
|
|
struct rcu_head rcu;
|
|
};
|
|
|
|
struct fib_rule_notifier_info {
|
|
struct fib_notifier_info info; /* must be first */
|
|
struct fib_rule *rule;
|
|
};
|
|
|
|
#define FRA_GENERIC_POLICY \
|
|
[FRA_UNSPEC] = { .strict_start_type = FRA_DPORT_RANGE + 1 }, \
|
|
[FRA_IIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
|
|
[FRA_OIFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, \
|
|
[FRA_PRIORITY] = { .type = NLA_U32 }, \
|
|
[FRA_FWMARK] = { .type = NLA_U32 }, \
|
|
[FRA_TUN_ID] = { .type = NLA_U64 }, \
|
|
[FRA_FWMASK] = { .type = NLA_U32 }, \
|
|
[FRA_TABLE] = { .type = NLA_U32 }, \
|
|
[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \
|
|
[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \
|
|
[FRA_GOTO] = { .type = NLA_U32 }, \
|
|
[FRA_L3MDEV] = { .type = NLA_U8 }, \
|
|
[FRA_UID_RANGE] = { .len = sizeof(struct fib_rule_uid_range) }, \
|
|
[FRA_PROTOCOL] = { .type = NLA_U8 }, \
|
|
[FRA_IP_PROTO] = { .type = NLA_U8 }, \
|
|
[FRA_SPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) }, \
|
|
[FRA_DPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) }
|
|
|
|
|
|
static inline void fib_rule_get(struct fib_rule *rule)
|
|
{
|
|
refcount_inc(&rule->refcnt);
|
|
}
|
|
|
|
static inline void fib_rule_put(struct fib_rule *rule)
|
|
{
|
|
if (refcount_dec_and_test(&rule->refcnt))
|
|
kfree_rcu(rule, rcu);
|
|
}
|
|
|
|
#ifdef CONFIG_NET_L3_MASTER_DEV
|
|
static inline u32 fib_rule_get_table(struct fib_rule *rule,
|
|
struct fib_lookup_arg *arg)
|
|
{
|
|
return rule->l3mdev ? arg->table : rule->table;
|
|
}
|
|
#else
|
|
static inline u32 fib_rule_get_table(struct fib_rule *rule,
|
|
struct fib_lookup_arg *arg)
|
|
{
|
|
return rule->table;
|
|
}
|
|
#endif
|
|
|
|
static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)
|
|
{
|
|
if (nla[FRA_TABLE])
|
|
return nla_get_u32(nla[FRA_TABLE]);
|
|
return frh->table;
|
|
}
|
|
|
|
static inline bool fib_rule_port_range_set(const struct fib_rule_port_range *range)
|
|
{
|
|
return range->start != 0 && range->end != 0;
|
|
}
|
|
|
|
static inline bool fib_rule_port_inrange(const struct fib_rule_port_range *a,
|
|
__be16 port)
|
|
{
|
|
return ntohs(port) >= a->start &&
|
|
ntohs(port) <= a->end;
|
|
}
|
|
|
|
static inline bool fib_rule_port_range_valid(const struct fib_rule_port_range *a)
|
|
{
|
|
return a->start != 0 && a->end != 0 && a->end < 0xffff &&
|
|
a->start <= a->end;
|
|
}
|
|
|
|
static inline bool fib_rule_port_range_compare(struct fib_rule_port_range *a,
|
|
struct fib_rule_port_range *b)
|
|
{
|
|
return a->start == b->start &&
|
|
a->end == b->end;
|
|
}
|
|
|
|
static inline bool fib_rule_requires_fldissect(struct fib_rule *rule)
|
|
{
|
|
return rule->iifindex != LOOPBACK_IFINDEX && (rule->ip_proto ||
|
|
fib_rule_port_range_set(&rule->sport_range) ||
|
|
fib_rule_port_range_set(&rule->dport_range));
|
|
}
|
|
|
|
struct fib_rules_ops *fib_rules_register(const struct fib_rules_ops *,
|
|
struct net *);
|
|
void fib_rules_unregister(struct fib_rules_ops *);
|
|
|
|
int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags,
|
|
struct fib_lookup_arg *);
|
|
int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table,
|
|
u32 flags);
|
|
bool fib_rule_matchall(const struct fib_rule *rule);
|
|
int fib_rules_dump(struct net *net, struct notifier_block *nb, int family,
|
|
struct netlink_ext_ack *extack);
|
|
unsigned int fib_rules_seq_read(struct net *net, int family);
|
|
|
|
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
struct netlink_ext_ack *extack);
|
|
int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
struct netlink_ext_ack *extack);
|
|
|
|
INDIRECT_CALLABLE_DECLARE(int fib6_rule_match(struct fib_rule *rule,
|
|
struct flowi *fl, int flags));
|
|
INDIRECT_CALLABLE_DECLARE(int fib4_rule_match(struct fib_rule *rule,
|
|
struct flowi *fl, int flags));
|
|
|
|
INDIRECT_CALLABLE_DECLARE(int fib6_rule_action(struct fib_rule *rule,
|
|
struct flowi *flp, int flags,
|
|
struct fib_lookup_arg *arg));
|
|
INDIRECT_CALLABLE_DECLARE(int fib4_rule_action(struct fib_rule *rule,
|
|
struct flowi *flp, int flags,
|
|
struct fib_lookup_arg *arg));
|
|
|
|
INDIRECT_CALLABLE_DECLARE(bool fib6_rule_suppress(struct fib_rule *rule,
|
|
int flags,
|
|
struct fib_lookup_arg *arg));
|
|
INDIRECT_CALLABLE_DECLARE(bool fib4_rule_suppress(struct fib_rule *rule,
|
|
int flags,
|
|
struct fib_lookup_arg *arg));
|
|
#endif
|