On 06/10/2016 04:40 AM, Subash Abhinov Kasiviswanathan wrote: > We have scripts which write to certain fields on 3.18 kernels but > this seems to be failing on 4.4 kernels. > An entry which we write to here is xfrm_aevent_rseqth which is u32. > > echo 4294967295 > /proc/sys/net/core/xfrm_aevent_rseqth
You could use echo -1 > /proc/sys/net/core/xfrm_aevent_rseq as a workaround before a correction is implemented. Best regards Heinrich > > Commit 230633d109e35b0a24277498e773edeb79b4a331 ("kernel/sysctl.c: > detect overflows when converting to int") prevented writing to > sysctl entries when integer overflow occurs. > However, this does not apply to unsigned integers. > > u32 should be able to hold 4294967295 here, however it fails due > to this check. > > static int do_proc_dointvec_conv(bool *negp, unsigned long *lvalp, > ... > if (*lvalp > (unsigned long) INT_MAX) > return -EINVAL; > > I would like to know if introducing a new handler proc_douintvec > would work here. Sample output and implementation below. This can be > cleaned up and added for other u32 fields in kernel. > > dev0# cat /proc/sys/net/core/xfrm_aevent_rseqth > 2 > dev0# echo 4294967295 > /proc/sys/net/core/xfrm_aevent_rseqth > dev0# cat /proc/sys/net/core/xfrm_aevent_rseqth > 4294967295 > dev0# > dev0# echo -1 > /proc/sys/net/core/xfrm_aevent_rseqth > bash: echo: write error: Invalid argument > > Signed-off-by: Subash Abhinov Kasiviswanathan <subas...@codeaurora.org> > --- > include/linux/sysctl.h | 2 ++ > kernel/sysctl.c | 32 ++++++++++++++++++++++++++++++++ > net/xfrm/xfrm_sysctl.c | 2 +- > 3 files changed, 35 insertions(+), 1 deletion(-) > > diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h > index fa7bc29..ef17db6c 100644 > --- a/include/linux/sysctl.h > +++ b/include/linux/sysctl.h > @@ -41,6 +41,8 @@ extern int proc_dostring(struct ctl_table *, int, > void __user *, size_t *, loff_t *); > extern int proc_dointvec(struct ctl_table *, int, > void __user *, size_t *, loff_t *); > +extern int proc_douintvec(struct ctl_table *, int, > + void __user *, size_t *, loff_t *); > extern int proc_dointvec_minmax(struct ctl_table *, int, > void __user *, size_t *, loff_t *); > extern int proc_dointvec_jiffies(struct ctl_table *, int, > diff --git a/kernel/sysctl.c b/kernel/sysctl.c > index 725587f..6362859 100644 > --- a/kernel/sysctl.c > +++ b/kernel/sysctl.c > @@ -2094,6 +2094,21 @@ static int do_proc_dointvec_conv(bool *negp, unsigned > long *lvalp, > return 0; > } > > +static int do_proc_douintvec_conv(bool *negp, unsigned long *lvalp, > + int *valp, > + int write, void *data) > +{ > + if (write) { > + if (*negp) > + return -EINVAL; > + *valp = *lvalp; > + } else { > + unsigned int val = *valp; > + *lvalp = (unsigned long)val; > + } > + return 0; > +} > + > static const char proc_wspace_sep[] = { ' ', '\t', '\n' }; > > static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table, > @@ -2217,6 +2232,16 @@ int proc_dointvec(struct ctl_table *table, int write, > NULL,NULL); > } > > +/** > + * proc_douintvec - read a vector of unsigned integers > + */ > +int proc_douintvec(struct ctl_table *table, int write, > + void __user *buffer, size_t *lenp, loff_t *ppos) > +{ > + return do_proc_dointvec(table,write,buffer,lenp,ppos, > + do_proc_douintvec_conv, NULL); > +} > + > /* > * Taint values can only be increased > * This means we can safely use a temporary. > @@ -2812,6 +2837,12 @@ int proc_dointvec(struct ctl_table *table, int write, > return -ENOSYS; > } > > +int proc_douintvec(struct ctl_table *table, int write, > + void __user *buffer, size_t *lenp, loff_t *ppos) > +{ > + return -ENOSYS; > +} > + > int proc_dointvec_minmax(struct ctl_table *table, int write, > void __user *buffer, size_t *lenp, loff_t *ppos) > { > @@ -2857,6 +2888,7 @@ int proc_doulongvec_ms_jiffies_minmax(struct ctl_table > *table, int write, > * exception granted :-) > */ > EXPORT_SYMBOL(proc_dointvec); > +EXPORT_SYMBOL(proc_douintvec); > EXPORT_SYMBOL(proc_dointvec_jiffies); > EXPORT_SYMBOL(proc_dointvec_minmax); > EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); > diff --git a/net/xfrm/xfrm_sysctl.c b/net/xfrm/xfrm_sysctl.c > index 05a6e3d..1fa3b1a 100644 > --- a/net/xfrm/xfrm_sysctl.c > +++ b/net/xfrm/xfrm_sysctl.c > @@ -23,7 +23,7 @@ static struct ctl_table xfrm_table[] = { > .procname = "xfrm_aevent_rseqth", > .maxlen = sizeof(u32), > .mode = 0644, > - .proc_handler = proc_dointvec > + .proc_handler = proc_douintvec > }, > { > .procname = "xfrm_larval_drop", >