Message ID | 1497646966-11806-1-git-send-email-gvrose8192@gmail.com |
---|---|
State | Superseded |
Headers | show |
On 06/16/2017 02:02 PM, Greg Rose wrote: > The attribute __ro_after_init was introduced in Linux kernel 4.5. If > a data structure is given this attribute then after the driver module > loads the memory page where the data resides will be marked read only. > > The compat code in cache.h always defines __ro_after_init if it is not > already defined so that it can be used as an attribute for the datapath > genl_family structure definitions. If __ro_after_init is defined then > it is used "as-is" where it will apply the read only attribute after > driver initialization. > > This is incorrect usage for the Generic Netlink genl_family structure > definitions prior to Linux kernel 4.10. The genl_family structure > in those kernels includes a list header member that will be written > to when the generic netlink family is unregistered. This will cause > a subsequent page fault and kernel panic because at this time the > genl_family structure data has been marked read only in the page > descriptor. > > A new compat macro is introduced in acinclude.m4 to detect when the > genl_family structure has the family_list list header as a member. > In this case HAVE_GENL_FAMILY_LIST is defined and if __ro_after_init > is also defined then it is undefined and redefined as empty. This > will prevent the genl_family data structure from being marked read > only in kernels 4.5 through 4.9 and thus prevent the page fault when > the generic netlink families in datapath.c are unregistered. Oops - wrong patch. There's supposed to be a signed off by and fixes tag. I'll resend. - Greg > --- > acinclude.m4 | 3 +++ > datapath/linux/compat/include/linux/cache.h | 9 ++++++++- > 2 files changed, 11 insertions(+), 1 deletion(-) > > diff --git a/acinclude.m4 b/acinclude.m4 > index 22cb897..2145ecc 100644 > --- a/acinclude.m4 > +++ b/acinclude.m4 > @@ -736,6 +736,9 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ > OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/ipv6/nf_defrag_ipv6.h], > [nf_defrag_ipv6_enable], [net], > [OVS_DEFINE([HAVE_DEFRAG_ENABLE_TAKES_NET])]) > + OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [family_list], > + [OVS_DEFINE([HAVE_GENL_FAMILY_LIST])]) > + > > if cmp -s datapath/linux/kcompat.h.new \ > datapath/linux/kcompat.h >/dev/null 2>&1; then > diff --git a/datapath/linux/compat/include/linux/cache.h b/datapath/linux/compat/include/linux/cache.h > index 917defa..35da4e7 100644 > --- a/datapath/linux/compat/include/linux/cache.h > +++ b/datapath/linux/compat/include/linux/cache.h > @@ -3,8 +3,15 @@ > > #include_next <linux/cache.h> > > +#ifdef HAVE_GENL_FAMILY_LIST > +#ifdef __ro_after_init > +#undef __ro_after_init > +#endif /* #ifdef __ro_after_init */ > +#define __ro_after_init > +#else > #ifndef __ro_after_init > #define __ro_after_init > -#endif > +#endif /* #ifndef __ro_after_init */ > +#endif /* #ifdef HAVE_GENL_FAMILY_LIST */ > > #endif >
diff --git a/acinclude.m4 b/acinclude.m4 index 22cb897..2145ecc 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -736,6 +736,9 @@ AC_DEFUN([OVS_CHECK_LINUX_COMPAT], [ OVS_FIND_PARAM_IFELSE([$KSRC/include/net/netfilter/ipv6/nf_defrag_ipv6.h], [nf_defrag_ipv6_enable], [net], [OVS_DEFINE([HAVE_DEFRAG_ENABLE_TAKES_NET])]) + OVS_GREP_IFELSE([$KSRC/include/net/genetlink.h], [family_list], + [OVS_DEFINE([HAVE_GENL_FAMILY_LIST])]) + if cmp -s datapath/linux/kcompat.h.new \ datapath/linux/kcompat.h >/dev/null 2>&1; then diff --git a/datapath/linux/compat/include/linux/cache.h b/datapath/linux/compat/include/linux/cache.h index 917defa..35da4e7 100644 --- a/datapath/linux/compat/include/linux/cache.h +++ b/datapath/linux/compat/include/linux/cache.h @@ -3,8 +3,15 @@ #include_next <linux/cache.h> +#ifdef HAVE_GENL_FAMILY_LIST +#ifdef __ro_after_init +#undef __ro_after_init +#endif /* #ifdef __ro_after_init */ +#define __ro_after_init +#else #ifndef __ro_after_init #define __ro_after_init -#endif +#endif /* #ifndef __ro_after_init */ +#endif /* #ifdef HAVE_GENL_FAMILY_LIST */ #endif