Skip to content

Commit ef15385

Browse files
committed
sysctl: Replace unidirectional INT converter macros with functions
Replace SYSCTL_USER_TO_KERN_INT_CONV and SYSCTL_KERN_TO_USER_INT_CONV macros with function implementing the same logic.This makes debugging easier and aligns with the functions preference described in coding-style.rst. Update all jiffies converters to use explicit function implementations instead of macro-generated versions. Signed-off-by: Joel Granados <joel.granados@kernel.org>
1 parent b3af263 commit ef15385

3 files changed

Lines changed: 167 additions & 69 deletions

File tree

include/linux/sysctl.h

Lines changed: 7 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -74,40 +74,6 @@ extern const int sysctl_vals[];
7474
#define SYSCTL_KERN_TO_USER(dir) (!dir)
7575

7676
#ifdef CONFIG_PROC_SYSCTL
77-
#define SYSCTL_USER_TO_KERN_INT_CONV(name, u_ptr_op) \
78-
int sysctl_user_to_kern_int_conv##name(const bool *negp, \
79-
const unsigned long *u_ptr,\
80-
int *k_ptr) \
81-
{ \
82-
unsigned long u = u_ptr_op(*u_ptr); \
83-
if (*negp) { \
84-
if (u > (unsigned long) INT_MAX + 1) \
85-
return -EINVAL; \
86-
WRITE_ONCE(*k_ptr, -u); \
87-
} else { \
88-
if (u > (unsigned long) INT_MAX) \
89-
return -EINVAL; \
90-
WRITE_ONCE(*k_ptr, u); \
91-
} \
92-
return 0; \
93-
}
94-
95-
#define SYSCTL_KERN_TO_USER_INT_CONV(name, k_ptr_op) \
96-
int sysctl_kern_to_user_int_conv##name(bool *negp, \
97-
unsigned long *u_ptr, \
98-
const int *k_ptr) \
99-
{ \
100-
int val = READ_ONCE(*k_ptr); \
101-
if (val < 0) { \
102-
*negp = true; \
103-
*u_ptr = -k_ptr_op((unsigned long)val); \
104-
} else { \
105-
*negp = false; \
106-
*u_ptr = k_ptr_op((unsigned long)val); \
107-
} \
108-
return 0; \
109-
}
110-
11177
/**
11278
* To range check on a converted value, use a temp k_ptr
11379
* When checking range, value should be within (tbl->extra1, tbl->extra2)
@@ -135,22 +101,8 @@ int do_proc_int_conv##name(bool *negp, unsigned long *u_ptr, int *k_ptr,\
135101
return user_to_kern(negp, u_ptr, k_ptr); \
136102
return 0; \
137103
}
138-
#else // CONFIG_PROC_SYSCTL
139-
#define SYSCTL_USER_TO_KERN_INT_CONV(name, u_ptr_op) \
140-
int sysctl_user_to_kern_int_conv##name(const bool *negp, \
141-
const unsigned long *u_ptr,\
142-
int *k_ptr) \
143-
{ \
144-
return -ENOSYS; \
145-
}
146104

147-
#define SYSCTL_KERN_TO_USER_INT_CONV(name, k_ptr_op) \
148-
int sysctl_kern_to_user_int_conv##name(bool *negp, \
149-
unsigned long *u_ptr, \
150-
const int *k_ptr) \
151-
{ \
152-
return -ENOSYS; \
153-
}
105+
#else // CONFIG_PROC_SYSCTL
154106

155107
#define SYSCTL_INT_CONV_CUSTOM(name, user_to_kern, kern_to_user, \
156108
k_ptr_range_check) \
@@ -170,13 +122,19 @@ typedef int proc_handler(const struct ctl_table *ctl, int write, void *buffer,
170122
int proc_dostring(const struct ctl_table *, int, void *, size_t *, loff_t *);
171123
int proc_dobool(const struct ctl_table *table, int write, void *buffer,
172124
size_t *lenp, loff_t *ppos);
125+
173126
int proc_dointvec(const struct ctl_table *, int, void *, size_t *, loff_t *);
174127
int proc_dointvec_minmax(const struct ctl_table *table, int dir, void *buffer,
175128
size_t *lenp, loff_t *ppos);
176129
int proc_dointvec_conv(const struct ctl_table *table, int dir, void *buffer,
177130
size_t *lenp, loff_t *ppos,
178131
int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
179132
int dir, const struct ctl_table *table));
133+
int proc_int_k2u_conv_kop(ulong *u_ptr, const int *k_ptr, bool *negp,
134+
ulong (*k_ptr_op)(const ulong));
135+
int proc_int_u2k_conv_uop(const ulong *u_ptr, int *k_ptr, const bool *negp,
136+
ulong (*u_ptr_op)(const ulong));
137+
180138
int proc_douintvec(const struct ctl_table *, int, void *, size_t *, loff_t *);
181139
int proc_douintvec_minmax(const struct ctl_table *table, int write, void *buffer,
182140
size_t *lenp, loff_t *ppos);

kernel/sysctl.c

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,73 @@ static int do_proc_uint_conv_minmax(ulong *u_ptr, uint *k_ptr, int dir,
458458
proc_uint_u2k_conv, proc_uint_k2u_conv);
459459
}
460460

461-
static SYSCTL_USER_TO_KERN_INT_CONV(, SYSCTL_CONV_IDENTITY)
462-
static SYSCTL_KERN_TO_USER_INT_CONV(, SYSCTL_CONV_IDENTITY)
461+
/**
462+
* proc_int_k2u_conv_kop - Assign kernel value to a user space pointer
463+
* @u_ptr: pointer to user space variable
464+
* @k_ptr: pointer to kernel variable
465+
* @negp: assigned %TRUE if the converted kernel value is negative;
466+
* %FALSE otherweise
467+
* @k_ptr_op: execute this function before assigning to u_ptr
468+
*
469+
* Uses READ_ONCE to get value from k_ptr. Executes k_ptr_op before assigning
470+
* to u_ptr if not NULL. Does **not** check for overflow.
471+
*
472+
* Returns: 0 on success.
473+
*/
474+
int proc_int_k2u_conv_kop(ulong *u_ptr, const int *k_ptr, bool *negp,
475+
ulong (*k_ptr_op)(const ulong))
476+
{
477+
int val = READ_ONCE(*k_ptr);
478+
479+
if (val < 0) {
480+
*negp = true;
481+
*u_ptr = k_ptr_op ? -k_ptr_op((ulong)val) : -(ulong)val;
482+
} else {
483+
*negp = false;
484+
*u_ptr = k_ptr_op ? k_ptr_op((ulong)val) : (ulong) val;
485+
}
486+
return 0;
487+
}
488+
489+
/**
490+
* proc_int_u2k_conv_uop - Assign user value to a kernel pointer
491+
* @u_ptr: pointer to user space variable
492+
* @k_ptr: pointer to kernel variable
493+
* @negp: If %TRUE, the converted user value is made negative.
494+
* @u_ptr_op: execute this function before assigning to k_ptr
495+
*
496+
* Uses WRITE_ONCE to assign value to k_ptr. Executes u_ptr_op if
497+
* not NULL. Check for overflow with UINT_MAX.
498+
*
499+
* Returns: 0 on success.
500+
*/
501+
int proc_int_u2k_conv_uop(const ulong *u_ptr, int *k_ptr, const bool *negp,
502+
ulong (*u_ptr_op)(const ulong))
503+
{
504+
ulong u = u_ptr_op ? u_ptr_op(*u_ptr) : *u_ptr;
505+
506+
if (*negp) {
507+
if (u > (ulong) INT_MAX + 1)
508+
return -EINVAL;
509+
WRITE_ONCE(*k_ptr, -u);
510+
} else {
511+
if (u > (ulong) INT_MAX)
512+
return -EINVAL;
513+
WRITE_ONCE(*k_ptr, u);
514+
}
515+
return 0;
516+
}
517+
518+
static int sysctl_user_to_kern_int_conv(const bool *negp, const ulong *u_ptr,
519+
int *k_ptr)
520+
{
521+
return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, NULL);
522+
}
523+
524+
static int sysctl_kern_to_user_int_conv(bool *negp, ulong *u_ptr, const int *k_ptr)
525+
{
526+
return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, NULL);
527+
}
463528

464529
static SYSCTL_INT_CONV_CUSTOM(, sysctl_user_to_kern_int_conv,
465530
sysctl_kern_to_user_int_conv, false)

kernel/time/jiffies.c

Lines changed: 93 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -100,26 +100,101 @@ void __init register_refined_jiffies(long cycles_per_second)
100100
__clocksource_register(&refined_jiffies);
101101
}
102102

103-
#define SYSCTL_CONV_MULT_HZ(val) ((val) * HZ)
104-
#define SYSCTL_CONV_DIV_HZ(val) ((val) / HZ)
105-
106-
static SYSCTL_USER_TO_KERN_INT_CONV(_hz, SYSCTL_CONV_MULT_HZ)
107-
static SYSCTL_KERN_TO_USER_INT_CONV(_hz, SYSCTL_CONV_DIV_HZ)
108-
static SYSCTL_USER_TO_KERN_INT_CONV(_userhz, clock_t_to_jiffies)
109-
static SYSCTL_KERN_TO_USER_INT_CONV(_userhz, jiffies_to_clock_t)
110-
static SYSCTL_USER_TO_KERN_INT_CONV(_ms, msecs_to_jiffies)
111-
static SYSCTL_KERN_TO_USER_INT_CONV(_ms, jiffies_to_msecs)
112-
113-
static SYSCTL_INT_CONV_CUSTOM(_jiffies, sysctl_user_to_kern_int_conv_hz,
114-
sysctl_kern_to_user_int_conv_hz, false)
103+
#ifdef CONFIG_PROC_SYSCTL
104+
static ulong mult_hz(const ulong val)
105+
{
106+
return val * HZ;
107+
}
108+
109+
static ulong div_hz(const ulong val)
110+
{
111+
return val / HZ;
112+
}
113+
114+
static int sysctl_u2k_int_conv_hz(const bool *negp, const ulong *u_ptr, int *k_ptr)
115+
{
116+
return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, mult_hz);
117+
}
118+
119+
static int sysctl_k2u_int_conv_hz(bool *negp, ulong *u_ptr, const int *k_ptr)
120+
{
121+
return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, div_hz);
122+
}
123+
124+
static int sysctl_u2k_int_conv_userhz(const bool *negp, const ulong *u_ptr, int *k_ptr)
125+
{
126+
return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, clock_t_to_jiffies);
127+
}
128+
129+
static ulong sysctl_jiffies_to_clock_t(const ulong val)
130+
{
131+
return jiffies_to_clock_t(val);
132+
}
133+
134+
static int sysctl_k2u_int_conv_userhz(bool *negp, ulong *u_ptr, const int *k_ptr)
135+
{
136+
return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, sysctl_jiffies_to_clock_t);
137+
}
138+
139+
static ulong sysctl_msecs_to_jiffies(const ulong val)
140+
{
141+
return msecs_to_jiffies(val);
142+
}
143+
144+
static int sysctl_u2k_int_conv_ms(const bool *negp, const ulong *u_ptr, int *k_ptr)
145+
{
146+
return proc_int_u2k_conv_uop(u_ptr, k_ptr, negp, sysctl_msecs_to_jiffies);
147+
}
148+
149+
static ulong sysctl_jiffies_to_msecs(const ulong val)
150+
{
151+
return jiffies_to_msecs(val);
152+
}
153+
154+
static int sysctl_k2u_int_conv_ms(bool *negp, ulong *u_ptr, const int *k_ptr)
155+
{
156+
return proc_int_k2u_conv_kop(u_ptr, k_ptr, negp, sysctl_jiffies_to_msecs);
157+
}
158+
159+
160+
static SYSCTL_INT_CONV_CUSTOM(_jiffies, sysctl_u2k_int_conv_hz,
161+
sysctl_k2u_int_conv_hz, false)
115162
static SYSCTL_INT_CONV_CUSTOM(_userhz_jiffies,
116-
sysctl_user_to_kern_int_conv_userhz,
117-
sysctl_kern_to_user_int_conv_userhz, false)
118-
static SYSCTL_INT_CONV_CUSTOM(_ms_jiffies, sysctl_user_to_kern_int_conv_ms,
119-
sysctl_kern_to_user_int_conv_ms, false)
163+
sysctl_u2k_int_conv_userhz,
164+
sysctl_k2u_int_conv_userhz, false)
165+
static SYSCTL_INT_CONV_CUSTOM(_ms_jiffies, sysctl_u2k_int_conv_ms,
166+
sysctl_k2u_int_conv_ms, false)
120167
static SYSCTL_INT_CONV_CUSTOM(_ms_jiffies_minmax,
121-
sysctl_user_to_kern_int_conv_ms,
122-
sysctl_kern_to_user_int_conv_ms, true)
168+
sysctl_u2k_int_conv_ms,
169+
sysctl_k2u_int_conv_ms, true)
170+
171+
#else // CONFIG_PROC_SYSCTL
172+
static int do_proc_int_conv_jiffies(bool *negp, ulong *u_ptr, int *k_ptr,
173+
int dir, const struct ctl_table *tbl)
174+
{
175+
return -ENOSYS;
176+
}
177+
178+
static int do_proc_int_conv_userhz_jiffies(bool *negp, ulong *u_ptr,
179+
int *k_ptr, int dir,
180+
const struct ctl_table *tbl)
181+
{
182+
return -ENOSYS;
183+
}
184+
185+
static int do_proc_int_conv_ms_jiffies(bool *negp, ulong *u_ptr, int *k_ptr,
186+
int dir, const struct ctl_table *tbl)
187+
{
188+
return -ENOSYS;
189+
}
190+
191+
static int do_proc_int_conv_ms_jiffies_minmax(bool *negp, ulong *u_ptr,
192+
int *k_ptr, int dir,
193+
const struct ctl_table *tbl)
194+
{
195+
return -ENOSYS;
196+
}
197+
#endif
123198

124199
/**
125200
* proc_dointvec_jiffies - read a vector of integers as seconds

0 commit comments

Comments
 (0)