Loading net/netfilter/xt_TEE.c +59 −17 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <linux/skbuff.h> #include <linux/skbuff.h> #include <linux/route.h> #include <linux/route.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h> #include <net/net_namespace.h> #include <net/netns/generic.h> #include <net/route.h> #include <net/route.h> #include <net/netfilter/ipv4/nf_dup_ipv4.h> #include <net/netfilter/ipv4/nf_dup_ipv4.h> #include <net/netfilter/ipv6/nf_dup_ipv6.h> #include <net/netfilter/ipv6/nf_dup_ipv6.h> Loading @@ -25,8 +27,15 @@ struct xt_tee_priv { int oif; int oif; }; }; static unsigned int tee_net_id __read_mostly; static const union nf_inet_addr tee_zero_address; static const union nf_inet_addr tee_zero_address; struct tee_net { struct list_head priv_list; /* lock protects the priv_list */ struct mutex lock; }; static unsigned int static unsigned int tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) { { Loading @@ -51,17 +60,16 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par) } } #endif #endif static DEFINE_MUTEX(priv_list_mutex); static LIST_HEAD(priv_list); static int tee_netdev_event(struct notifier_block *this, unsigned long event, static int tee_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) void *ptr) { { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct tee_net *tn = net_generic(net, tee_net_id); struct xt_tee_priv *priv; struct xt_tee_priv *priv; mutex_lock(&priv_list_mutex); mutex_lock(&tn->lock); list_for_each_entry(priv, &priv_list, list) { list_for_each_entry(priv, &tn->priv_list, list) { switch (event) { switch (event) { case NETDEV_REGISTER: case NETDEV_REGISTER: if (!strcmp(dev->name, priv->tginfo->oif)) if (!strcmp(dev->name, priv->tginfo->oif)) Loading @@ -79,13 +87,14 @@ static int tee_netdev_event(struct notifier_block *this, unsigned long event, break; break; } } } } mutex_unlock(&priv_list_mutex); mutex_unlock(&tn->lock); return NOTIFY_DONE; return NOTIFY_DONE; } } static int tee_tg_check(const struct xt_tgchk_param *par) static int tee_tg_check(const struct xt_tgchk_param *par) { { struct tee_net *tn = net_generic(par->net, tee_net_id); struct xt_tee_tginfo *info = par->targinfo; struct xt_tee_tginfo *info = par->targinfo; struct xt_tee_priv *priv; struct xt_tee_priv *priv; Loading @@ -95,6 +104,8 @@ static int tee_tg_check(const struct xt_tgchk_param *par) return -EINVAL; return -EINVAL; if (info->oif[0]) { if (info->oif[0]) { struct net_device *dev; if (info->oif[sizeof(info->oif)-1] != '\0') if (info->oif[sizeof(info->oif)-1] != '\0') return -EINVAL; return -EINVAL; Loading @@ -106,9 +117,14 @@ static int tee_tg_check(const struct xt_tgchk_param *par) priv->oif = -1; priv->oif = -1; info->priv = priv; info->priv = priv; mutex_lock(&priv_list_mutex); dev = dev_get_by_name(par->net, info->oif); list_add(&priv->list, &priv_list); if (dev) { mutex_unlock(&priv_list_mutex); priv->oif = dev->ifindex; dev_put(dev); } mutex_lock(&tn->lock); list_add(&priv->list, &tn->priv_list); mutex_unlock(&tn->lock); } else } else info->priv = NULL; info->priv = NULL; Loading @@ -118,12 +134,13 @@ static int tee_tg_check(const struct xt_tgchk_param *par) static void tee_tg_destroy(const struct xt_tgdtor_param *par) static void tee_tg_destroy(const struct xt_tgdtor_param *par) { { struct tee_net *tn = net_generic(par->net, tee_net_id); struct xt_tee_tginfo *info = par->targinfo; struct xt_tee_tginfo *info = par->targinfo; if (info->priv) { if (info->priv) { mutex_lock(&priv_list_mutex); mutex_lock(&tn->lock); list_del(&info->priv->list); list_del(&info->priv->list); mutex_unlock(&priv_list_mutex); mutex_unlock(&tn->lock); kfree(info->priv); kfree(info->priv); } } static_key_slow_dec(&xt_tee_enabled); static_key_slow_dec(&xt_tee_enabled); Loading Loading @@ -156,6 +173,21 @@ static struct xt_target tee_tg_reg[] __read_mostly = { #endif #endif }; }; static int __net_init tee_net_init(struct net *net) { struct tee_net *tn = net_generic(net, tee_net_id); INIT_LIST_HEAD(&tn->priv_list); mutex_init(&tn->lock); return 0; } static struct pernet_operations tee_net_ops = { .init = tee_net_init, .id = &tee_net_id, .size = sizeof(struct tee_net), }; static struct notifier_block tee_netdev_notifier = { static struct notifier_block tee_netdev_notifier = { .notifier_call = tee_netdev_event, .notifier_call = tee_netdev_event, }; }; Loading @@ -164,22 +196,32 @@ static int __init tee_tg_init(void) { { int ret; int ret; ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); ret = register_pernet_subsys(&tee_net_ops); if (ret) if (ret < 0) return ret; return ret; ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); if (ret < 0) goto cleanup_subsys; ret = register_netdevice_notifier(&tee_netdev_notifier); ret = register_netdevice_notifier(&tee_netdev_notifier); if (ret) { if (ret < 0) xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); goto unregister_targets; return ret; } return 0; return 0; unregister_targets: xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); cleanup_subsys: unregister_pernet_subsys(&tee_net_ops); return ret; } } static void __exit tee_tg_exit(void) static void __exit tee_tg_exit(void) { { unregister_netdevice_notifier(&tee_netdev_notifier); unregister_netdevice_notifier(&tee_netdev_notifier); xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); unregister_pernet_subsys(&tee_net_ops); } } module_init(tee_tg_init); module_init(tee_tg_init); Loading Loading
net/netfilter/xt_TEE.c +59 −17 Original line number Original line Diff line number Diff line Loading @@ -14,6 +14,8 @@ #include <linux/skbuff.h> #include <linux/skbuff.h> #include <linux/route.h> #include <linux/route.h> #include <linux/netfilter/x_tables.h> #include <linux/netfilter/x_tables.h> #include <net/net_namespace.h> #include <net/netns/generic.h> #include <net/route.h> #include <net/route.h> #include <net/netfilter/ipv4/nf_dup_ipv4.h> #include <net/netfilter/ipv4/nf_dup_ipv4.h> #include <net/netfilter/ipv6/nf_dup_ipv6.h> #include <net/netfilter/ipv6/nf_dup_ipv6.h> Loading @@ -25,8 +27,15 @@ struct xt_tee_priv { int oif; int oif; }; }; static unsigned int tee_net_id __read_mostly; static const union nf_inet_addr tee_zero_address; static const union nf_inet_addr tee_zero_address; struct tee_net { struct list_head priv_list; /* lock protects the priv_list */ struct mutex lock; }; static unsigned int static unsigned int tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) tee_tg4(struct sk_buff *skb, const struct xt_action_param *par) { { Loading @@ -51,17 +60,16 @@ tee_tg6(struct sk_buff *skb, const struct xt_action_param *par) } } #endif #endif static DEFINE_MUTEX(priv_list_mutex); static LIST_HEAD(priv_list); static int tee_netdev_event(struct notifier_block *this, unsigned long event, static int tee_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) void *ptr) { { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct net *net = dev_net(dev); struct tee_net *tn = net_generic(net, tee_net_id); struct xt_tee_priv *priv; struct xt_tee_priv *priv; mutex_lock(&priv_list_mutex); mutex_lock(&tn->lock); list_for_each_entry(priv, &priv_list, list) { list_for_each_entry(priv, &tn->priv_list, list) { switch (event) { switch (event) { case NETDEV_REGISTER: case NETDEV_REGISTER: if (!strcmp(dev->name, priv->tginfo->oif)) if (!strcmp(dev->name, priv->tginfo->oif)) Loading @@ -79,13 +87,14 @@ static int tee_netdev_event(struct notifier_block *this, unsigned long event, break; break; } } } } mutex_unlock(&priv_list_mutex); mutex_unlock(&tn->lock); return NOTIFY_DONE; return NOTIFY_DONE; } } static int tee_tg_check(const struct xt_tgchk_param *par) static int tee_tg_check(const struct xt_tgchk_param *par) { { struct tee_net *tn = net_generic(par->net, tee_net_id); struct xt_tee_tginfo *info = par->targinfo; struct xt_tee_tginfo *info = par->targinfo; struct xt_tee_priv *priv; struct xt_tee_priv *priv; Loading @@ -95,6 +104,8 @@ static int tee_tg_check(const struct xt_tgchk_param *par) return -EINVAL; return -EINVAL; if (info->oif[0]) { if (info->oif[0]) { struct net_device *dev; if (info->oif[sizeof(info->oif)-1] != '\0') if (info->oif[sizeof(info->oif)-1] != '\0') return -EINVAL; return -EINVAL; Loading @@ -106,9 +117,14 @@ static int tee_tg_check(const struct xt_tgchk_param *par) priv->oif = -1; priv->oif = -1; info->priv = priv; info->priv = priv; mutex_lock(&priv_list_mutex); dev = dev_get_by_name(par->net, info->oif); list_add(&priv->list, &priv_list); if (dev) { mutex_unlock(&priv_list_mutex); priv->oif = dev->ifindex; dev_put(dev); } mutex_lock(&tn->lock); list_add(&priv->list, &tn->priv_list); mutex_unlock(&tn->lock); } else } else info->priv = NULL; info->priv = NULL; Loading @@ -118,12 +134,13 @@ static int tee_tg_check(const struct xt_tgchk_param *par) static void tee_tg_destroy(const struct xt_tgdtor_param *par) static void tee_tg_destroy(const struct xt_tgdtor_param *par) { { struct tee_net *tn = net_generic(par->net, tee_net_id); struct xt_tee_tginfo *info = par->targinfo; struct xt_tee_tginfo *info = par->targinfo; if (info->priv) { if (info->priv) { mutex_lock(&priv_list_mutex); mutex_lock(&tn->lock); list_del(&info->priv->list); list_del(&info->priv->list); mutex_unlock(&priv_list_mutex); mutex_unlock(&tn->lock); kfree(info->priv); kfree(info->priv); } } static_key_slow_dec(&xt_tee_enabled); static_key_slow_dec(&xt_tee_enabled); Loading Loading @@ -156,6 +173,21 @@ static struct xt_target tee_tg_reg[] __read_mostly = { #endif #endif }; }; static int __net_init tee_net_init(struct net *net) { struct tee_net *tn = net_generic(net, tee_net_id); INIT_LIST_HEAD(&tn->priv_list); mutex_init(&tn->lock); return 0; } static struct pernet_operations tee_net_ops = { .init = tee_net_init, .id = &tee_net_id, .size = sizeof(struct tee_net), }; static struct notifier_block tee_netdev_notifier = { static struct notifier_block tee_netdev_notifier = { .notifier_call = tee_netdev_event, .notifier_call = tee_netdev_event, }; }; Loading @@ -164,22 +196,32 @@ static int __init tee_tg_init(void) { { int ret; int ret; ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); ret = register_pernet_subsys(&tee_net_ops); if (ret) if (ret < 0) return ret; return ret; ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); if (ret < 0) goto cleanup_subsys; ret = register_netdevice_notifier(&tee_netdev_notifier); ret = register_netdevice_notifier(&tee_netdev_notifier); if (ret) { if (ret < 0) xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); goto unregister_targets; return ret; } return 0; return 0; unregister_targets: xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); cleanup_subsys: unregister_pernet_subsys(&tee_net_ops); return ret; } } static void __exit tee_tg_exit(void) static void __exit tee_tg_exit(void) { { unregister_netdevice_notifier(&tee_netdev_notifier); unregister_netdevice_notifier(&tee_netdev_notifier); xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); unregister_pernet_subsys(&tee_net_ops); } } module_init(tee_tg_init); module_init(tee_tg_init); Loading