On 6/6/19 4:57 PM, Matteo Croce wrote:
> Some sysctl related code and data structures are never referenced
> when CONFIG_SYSCTL is not set.
> While this is usually harmless, it produces a build failure since sysctl
> shared variables exist, due to missing sysctl_vals symbol:
> 
>     ld: net/mpls/af_mpls.o: in function `mpls_platform_labels':
>     af_mpls.c:(.text+0x162a): undefined reference to `sysctl_vals'
>     ld: net/mpls/af_mpls.o:(.rodata+0x830): undefined reference to 
> `sysctl_vals'
>     ld: net/mpls/af_mpls.o:(.rodata+0x838): undefined reference to 
> `sysctl_vals'
>     ld: net/mpls/af_mpls.o:(.rodata+0x870): undefined reference to 
> `sysctl_vals'
> 
> Fix this by moving all sysctl related code under #ifdef CONFIG_SYSCTL
> 
> Reported-by: Randy Dunlap <rdun...@infradead.org>
> Signed-off-by: Matteo Croce <mcr...@redhat.com>

Builds for me.  Thanks.

Acked-by: Randy Dunlap <rdun...@infradead.org> # build-tested

> ---
>  net/mpls/af_mpls.c | 389 ++++++++++++++++++++++++---------------------
>  1 file changed, 204 insertions(+), 185 deletions(-)
> 
> diff --git a/net/mpls/af_mpls.c b/net/mpls/af_mpls.c
> index c312741df2ce..5aacbf129ec5 100644
> --- a/net/mpls/af_mpls.c
> +++ b/net/mpls/af_mpls.c
> @@ -37,9 +37,6 @@
>  
>  #define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
>  
> -static int label_limit = (1 << 20) - 1;
> -static int ttl_max = 255;
> -
>  #if IS_ENABLED(CONFIG_NET_IP_TUNNEL)
>  static size_t ipgre_mpls_encap_hlen(struct ip_tunnel_encap *e)
>  {
> @@ -1179,31 +1176,6 @@ static int mpls_netconf_msgsize_devconf(int type)
>       return size;
>  }
>  
> -static void mpls_netconf_notify_devconf(struct net *net, int event,
> -                                     int type, struct mpls_dev *mdev)
> -{
> -     struct sk_buff *skb;
> -     int err = -ENOBUFS;
> -
> -     skb = nlmsg_new(mpls_netconf_msgsize_devconf(type), GFP_KERNEL);
> -     if (!skb)
> -             goto errout;
> -
> -     err = mpls_netconf_fill_devconf(skb, mdev, 0, 0, event, 0, type);
> -     if (err < 0) {
> -             /* -EMSGSIZE implies BUG in mpls_netconf_msgsize_devconf() */
> -             WARN_ON(err == -EMSGSIZE);
> -             kfree_skb(skb);
> -             goto errout;
> -     }
> -
> -     rtnl_notify(skb, net, 0, RTNLGRP_MPLS_NETCONF, NULL, GFP_KERNEL);
> -     return;
> -errout:
> -     if (err < 0)
> -             rtnl_set_sk_err(net, RTNLGRP_MPLS_NETCONF, err);
> -}
> -
>  static const struct nla_policy devconf_mpls_policy[NETCONFA_MAX + 1] = {
>       [NETCONFA_IFINDEX]      = { .len = sizeof(int) },
>  };
> @@ -1362,6 +1334,36 @@ static int mpls_netconf_dump_devconf(struct sk_buff 
> *skb,
>  #define MPLS_PERDEV_SYSCTL_OFFSET(field)     \
>       (&((struct mpls_dev *)0)->field)
>  
> +#ifdef CONFIG_SYSCTL
> +
> +static int label_limit = (1 << 20) - 1;
> +static int ttl_max = 255;
> +
> +static void mpls_netconf_notify_devconf(struct net *net, int event,
> +                                     int type, struct mpls_dev *mdev)
> +{
> +     struct sk_buff *skb;
> +     int err = -ENOBUFS;
> +
> +     skb = nlmsg_new(mpls_netconf_msgsize_devconf(type), GFP_KERNEL);
> +     if (!skb)
> +             goto errout;
> +
> +     err = mpls_netconf_fill_devconf(skb, mdev, 0, 0, event, 0, type);
> +     if (err < 0) {
> +             /* -EMSGSIZE implies BUG in mpls_netconf_msgsize_devconf() */
> +             WARN_ON(err == -EMSGSIZE);
> +             kfree_skb(skb);
> +             goto errout;
> +     }
> +
> +     rtnl_notify(skb, net, 0, RTNLGRP_MPLS_NETCONF, NULL, GFP_KERNEL);
> +     return;
> +errout:
> +     if (err < 0)
> +             rtnl_set_sk_err(net, RTNLGRP_MPLS_NETCONF, err);
> +}
> +
>  static int mpls_conf_proc(struct ctl_table *ctl, int write,
>                         void __user *buffer,
>                         size_t *lenp, loff_t *ppos)
> @@ -1445,6 +1447,173 @@ static void mpls_dev_sysctl_unregister(struct 
> net_device *dev,
>       mpls_netconf_notify_devconf(net, RTM_DELNETCONF, 0, mdev);
>  }
>  
> +static int resize_platform_label_table(struct net *net, size_t limit)
> +{
> +     size_t size = sizeof(struct mpls_route *) * limit;
> +     size_t old_limit;
> +     size_t cp_size;
> +     struct mpls_route __rcu **labels = NULL, **old;
> +     struct mpls_route *rt0 = NULL, *rt2 = NULL;
> +     unsigned index;
> +
> +     if (size) {
> +             labels = kvzalloc(size, GFP_KERNEL);
> +             if (!labels)
> +                     goto nolabels;
> +     }
> +
> +     /* In case the predefined labels need to be populated */
> +     if (limit > MPLS_LABEL_IPV4NULL) {
> +             struct net_device *lo = net->loopback_dev;
> +             rt0 = mpls_rt_alloc(1, lo->addr_len, 0);
> +             if (IS_ERR(rt0))
> +                     goto nort0;
> +             RCU_INIT_POINTER(rt0->rt_nh->nh_dev, lo);
> +             rt0->rt_protocol = RTPROT_KERNEL;
> +             rt0->rt_payload_type = MPT_IPV4;
> +             rt0->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
> +             rt0->rt_nh->nh_via_table = NEIGH_LINK_TABLE;
> +             rt0->rt_nh->nh_via_alen = lo->addr_len;
> +             memcpy(__mpls_nh_via(rt0, rt0->rt_nh), lo->dev_addr,
> +                    lo->addr_len);
> +     }
> +     if (limit > MPLS_LABEL_IPV6NULL) {
> +             struct net_device *lo = net->loopback_dev;
> +             rt2 = mpls_rt_alloc(1, lo->addr_len, 0);
> +             if (IS_ERR(rt2))
> +                     goto nort2;
> +             RCU_INIT_POINTER(rt2->rt_nh->nh_dev, lo);
> +             rt2->rt_protocol = RTPROT_KERNEL;
> +             rt2->rt_payload_type = MPT_IPV6;
> +             rt2->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
> +             rt2->rt_nh->nh_via_table = NEIGH_LINK_TABLE;
> +             rt2->rt_nh->nh_via_alen = lo->addr_len;
> +             memcpy(__mpls_nh_via(rt2, rt2->rt_nh), lo->dev_addr,
> +                    lo->addr_len);
> +     }
> +
> +     rtnl_lock();
> +     /* Remember the original table */
> +     old = rtnl_dereference(net->mpls.platform_label);
> +     old_limit = net->mpls.platform_labels;
> +
> +     /* Free any labels beyond the new table */
> +     for (index = limit; index < old_limit; index++)
> +             mpls_route_update(net, index, NULL, NULL);
> +
> +     /* Copy over the old labels */
> +     cp_size = size;
> +     if (old_limit < limit)
> +             cp_size = old_limit * sizeof(struct mpls_route *);
> +
> +     memcpy(labels, old, cp_size);
> +
> +     /* If needed set the predefined labels */
> +     if ((old_limit <= MPLS_LABEL_IPV6NULL) &&
> +         (limit > MPLS_LABEL_IPV6NULL)) {
> +             RCU_INIT_POINTER(labels[MPLS_LABEL_IPV6NULL], rt2);
> +             rt2 = NULL;
> +     }
> +
> +     if ((old_limit <= MPLS_LABEL_IPV4NULL) &&
> +         (limit > MPLS_LABEL_IPV4NULL)) {
> +             RCU_INIT_POINTER(labels[MPLS_LABEL_IPV4NULL], rt0);
> +             rt0 = NULL;
> +     }
> +
> +     /* Update the global pointers */
> +     net->mpls.platform_labels = limit;
> +     rcu_assign_pointer(net->mpls.platform_label, labels);
> +
> +     rtnl_unlock();
> +
> +     mpls_rt_free(rt2);
> +     mpls_rt_free(rt0);
> +
> +     if (old) {
> +             synchronize_rcu();
> +             kvfree(old);
> +     }
> +     return 0;
> +
> +nort2:
> +     mpls_rt_free(rt0);
> +nort0:
> +     kvfree(labels);
> +nolabels:
> +     return -ENOMEM;
> +}
> +
> +static int mpls_platform_labels(struct ctl_table *table, int write,
> +                             void __user *buffer, size_t *lenp, loff_t *ppos)
> +{
> +     struct net *net = table->data;
> +     int platform_labels = net->mpls.platform_labels;
> +     int ret;
> +     struct ctl_table tmp = {
> +             .procname       = table->procname,
> +             .data           = &platform_labels,
> +             .maxlen         = sizeof(int),
> +             .mode           = table->mode,
> +             .extra1         = SYSCTL_ZERO,
> +             .extra2         = &label_limit,
> +     };
> +
> +     ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
> +
> +     if (write && ret == 0)
> +             ret = resize_platform_label_table(net, platform_labels);
> +
> +     return ret;
> +}
> +
> +#define MPLS_NS_SYSCTL_OFFSET(field)         \
> +     (&((struct net *)0)->field)
> +
> +static const struct ctl_table mpls_table[] = {
> +     {
> +             .procname       = "platform_labels",
> +             .data           = NULL,
> +             .maxlen         = sizeof(int),
> +             .mode           = 0644,
> +             .proc_handler   = mpls_platform_labels,
> +     },
> +     {
> +             .procname       = "ip_ttl_propagate",
> +             .data           = MPLS_NS_SYSCTL_OFFSET(mpls.ip_ttl_propagate),
> +             .maxlen         = sizeof(int),
> +             .mode           = 0644,
> +             .proc_handler   = proc_dointvec_minmax,
> +             .extra1         = SYSCTL_ZERO,
> +             .extra2         = SYSCTL_ONE,
> +     },
> +     {
> +             .procname       = "default_ttl",
> +             .data           = MPLS_NS_SYSCTL_OFFSET(mpls.default_ttl),
> +             .maxlen         = sizeof(int),
> +             .mode           = 0644,
> +             .proc_handler   = proc_dointvec_minmax,
> +             .extra1         = SYSCTL_ONE,
> +             .extra2         = &ttl_max,
> +     },
> +     { }
> +};
> +
> +#else
> +
> +static int mpls_dev_sysctl_register(struct net_device *dev,
> +                                 struct mpls_dev *mdev)
> +{
> +     return 0;
> +}
> +
> +static void mpls_dev_sysctl_unregister(struct net_device *dev,
> +                                    struct mpls_dev *mdev)
> +{
> +}
> +
> +#endif
> +
>  static struct mpls_dev *mpls_add_dev(struct net_device *dev)
>  {
>       struct mpls_dev *mdev;
> @@ -2497,168 +2666,12 @@ static int mpls_getroute(struct sk_buff *in_skb, 
> struct nlmsghdr *in_nlh,
>       return err;
>  }
>  
> -static int resize_platform_label_table(struct net *net, size_t limit)
> -{
> -     size_t size = sizeof(struct mpls_route *) * limit;
> -     size_t old_limit;
> -     size_t cp_size;
> -     struct mpls_route __rcu **labels = NULL, **old;
> -     struct mpls_route *rt0 = NULL, *rt2 = NULL;
> -     unsigned index;
> -
> -     if (size) {
> -             labels = kvzalloc(size, GFP_KERNEL);
> -             if (!labels)
> -                     goto nolabels;
> -     }
> -
> -     /* In case the predefined labels need to be populated */
> -     if (limit > MPLS_LABEL_IPV4NULL) {
> -             struct net_device *lo = net->loopback_dev;
> -             rt0 = mpls_rt_alloc(1, lo->addr_len, 0);
> -             if (IS_ERR(rt0))
> -                     goto nort0;
> -             RCU_INIT_POINTER(rt0->rt_nh->nh_dev, lo);
> -             rt0->rt_protocol = RTPROT_KERNEL;
> -             rt0->rt_payload_type = MPT_IPV4;
> -             rt0->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
> -             rt0->rt_nh->nh_via_table = NEIGH_LINK_TABLE;
> -             rt0->rt_nh->nh_via_alen = lo->addr_len;
> -             memcpy(__mpls_nh_via(rt0, rt0->rt_nh), lo->dev_addr,
> -                    lo->addr_len);
> -     }
> -     if (limit > MPLS_LABEL_IPV6NULL) {
> -             struct net_device *lo = net->loopback_dev;
> -             rt2 = mpls_rt_alloc(1, lo->addr_len, 0);
> -             if (IS_ERR(rt2))
> -                     goto nort2;
> -             RCU_INIT_POINTER(rt2->rt_nh->nh_dev, lo);
> -             rt2->rt_protocol = RTPROT_KERNEL;
> -             rt2->rt_payload_type = MPT_IPV6;
> -             rt2->rt_ttl_propagate = MPLS_TTL_PROP_DEFAULT;
> -             rt2->rt_nh->nh_via_table = NEIGH_LINK_TABLE;
> -             rt2->rt_nh->nh_via_alen = lo->addr_len;
> -             memcpy(__mpls_nh_via(rt2, rt2->rt_nh), lo->dev_addr,
> -                    lo->addr_len);
> -     }
> -
> -     rtnl_lock();
> -     /* Remember the original table */
> -     old = rtnl_dereference(net->mpls.platform_label);
> -     old_limit = net->mpls.platform_labels;
> -
> -     /* Free any labels beyond the new table */
> -     for (index = limit; index < old_limit; index++)
> -             mpls_route_update(net, index, NULL, NULL);
> -
> -     /* Copy over the old labels */
> -     cp_size = size;
> -     if (old_limit < limit)
> -             cp_size = old_limit * sizeof(struct mpls_route *);
> -
> -     memcpy(labels, old, cp_size);
> -
> -     /* If needed set the predefined labels */
> -     if ((old_limit <= MPLS_LABEL_IPV6NULL) &&
> -         (limit > MPLS_LABEL_IPV6NULL)) {
> -             RCU_INIT_POINTER(labels[MPLS_LABEL_IPV6NULL], rt2);
> -             rt2 = NULL;
> -     }
> -
> -     if ((old_limit <= MPLS_LABEL_IPV4NULL) &&
> -         (limit > MPLS_LABEL_IPV4NULL)) {
> -             RCU_INIT_POINTER(labels[MPLS_LABEL_IPV4NULL], rt0);
> -             rt0 = NULL;
> -     }
> -
> -     /* Update the global pointers */
> -     net->mpls.platform_labels = limit;
> -     rcu_assign_pointer(net->mpls.platform_label, labels);
> -
> -     rtnl_unlock();
> -
> -     mpls_rt_free(rt2);
> -     mpls_rt_free(rt0);
> -
> -     if (old) {
> -             synchronize_rcu();
> -             kvfree(old);
> -     }
> -     return 0;
> -
> -nort2:
> -     mpls_rt_free(rt0);
> -nort0:
> -     kvfree(labels);
> -nolabels:
> -     return -ENOMEM;
> -}
> -
> -static int mpls_platform_labels(struct ctl_table *table, int write,
> -                             void __user *buffer, size_t *lenp, loff_t *ppos)
> -{
> -     struct net *net = table->data;
> -     int platform_labels = net->mpls.platform_labels;
> -     int ret;
> -     struct ctl_table tmp = {
> -             .procname       = table->procname,
> -             .data           = &platform_labels,
> -             .maxlen         = sizeof(int),
> -             .mode           = table->mode,
> -             .extra1         = SYSCTL_ZERO,
> -             .extra2         = &label_limit,
> -     };
> -
> -     ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
> -
> -     if (write && ret == 0)
> -             ret = resize_platform_label_table(net, platform_labels);
> -
> -     return ret;
> -}
> -
> -#define MPLS_NS_SYSCTL_OFFSET(field)         \
> -     (&((struct net *)0)->field)
> -
> -static const struct ctl_table mpls_table[] = {
> -     {
> -             .procname       = "platform_labels",
> -             .data           = NULL,
> -             .maxlen         = sizeof(int),
> -             .mode           = 0644,
> -             .proc_handler   = mpls_platform_labels,
> -     },
> -     {
> -             .procname       = "ip_ttl_propagate",
> -             .data           = MPLS_NS_SYSCTL_OFFSET(mpls.ip_ttl_propagate),
> -             .maxlen         = sizeof(int),
> -             .mode           = 0644,
> -             .proc_handler   = proc_dointvec_minmax,
> -             .extra1         = SYSCTL_ZERO,
> -             .extra2         = SYSCTL_ONE,
> -     },
> -     {
> -             .procname       = "default_ttl",
> -             .data           = MPLS_NS_SYSCTL_OFFSET(mpls.default_ttl),
> -             .maxlen         = sizeof(int),
> -             .mode           = 0644,
> -             .proc_handler   = proc_dointvec_minmax,
> -             .extra1         = SYSCTL_ONE,
> -             .extra2         = &ttl_max,
> -     },
> -     { }
> -};
> -
>  static int mpls_net_init(struct net *net)
>  {
> +#ifdef CONFIG_SYSCTL
>       struct ctl_table *table;
>       int i;
>  
> -     net->mpls.platform_labels = 0;
> -     net->mpls.platform_label = NULL;
> -     net->mpls.ip_ttl_propagate = 1;
> -     net->mpls.default_ttl = 255;
> -
>       table = kmemdup(mpls_table, sizeof(mpls_table), GFP_KERNEL);
>       if (table == NULL)
>               return -ENOMEM;
> @@ -2674,6 +2687,12 @@ static int mpls_net_init(struct net *net)
>               kfree(table);
>               return -ENOMEM;
>       }
> +#endif
> +
> +     net->mpls.platform_labels = 0;
> +     net->mpls.platform_label = NULL;
> +     net->mpls.ip_ttl_propagate = 1;
> +     net->mpls.default_ttl = 255;
>  
>       return 0;
>  }
> 


-- 
~Randy

Reply via email to