Merge tag 'sysctl-7.03-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/sysctl/sysctl

Pull sysctl updates from Joel Granados:

 - Fix kernel-doc warnings by adjusting in file documentation

 - Consolidate do_proc_* function into do_proc_vec

   Consolidate three slightly different implementations of applying a
   converter on all elements of a vector. Fixes to this function now
   propagate to the three types.

 - Replace CONFIG_PROC_SYSCTL with CONFIG_SYSCTL (they were the same)
   and restrict cad_pid modifications to global root (GLOBAL_ROOT_UID)

* tag 'sysctl-7.03-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/sysctl/sysctl:
  sysctl: remove CONFIG_PROC_SYSCTL, it just mirrors CONFIG_SYSCTL
  sysctl: move the "cad_pid" entry from pid_table[] to kern_reboot_table[]
  sysctl: repair some kernel-doc comments
  sysctl: add Returns: kernel-doc for all functions
  sysctl: Update API function documentation
  sysctl: Rename proc_doulongvec_minmax_conv to proc_doulongvec_conv
  sysctl: Group proc_handler declarations and document
  sysctl: Replace do_proc_do{int,ulong,uint}vec with do_proc_vec
  sysctl: Add negp parameter to douintvec converter functions
  sysctl: Move default converter assignment out of do_proc_dointvec
This commit is contained in:
Linus Torvalds
2026-08-20 08:46:41 -07:00
25 changed files with 459 additions and 361 deletions

View File

@@ -74,7 +74,7 @@ CONFIG_RTC_DRV_DS1307=y
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
CONFIG_FSCACHE=y
# CONFIG_PROC_SYSCTL is not set
# CONFIG_SYSCTL is not set
CONFIG_JFFS2_FS=y
CONFIG_ROMFS_FS=y
CONFIG_ROMFS_BACKED_BY_BOTH=y

View File

@@ -87,7 +87,7 @@ CONFIG_EXT4_FS_SECURITY=y
# CONFIG_DNOTIFY is not set
# CONFIG_INOTIFY_USER is not set
CONFIG_OVERLAY_FS=y
# CONFIG_PROC_SYSCTL is not set
# CONFIG_SYSCTL is not set
CONFIG_SQUASHFS=y
CONFIG_XZ_DEC=y
CONFIG_PRINTK_TIME=y

View File

@@ -575,7 +575,7 @@ config HIPERDISPATCH_ON
def_bool y
bool "Use hiperdispatch on vertical polarization by default"
depends on SCHED_TOPOLOGY
depends on PROC_SYSCTL
depends on SYSCTL
help
Hiperdispatch aims to improve the CPU scheduler's decision
making when using vertical polarization by adjusting CPU
@@ -893,7 +893,7 @@ config CMM_IUCV
config APPLDATA_BASE
def_bool n
prompt "Linux - VM Monitor Stream, base infrastructure"
depends on PROC_SYSCTL
depends on SYSCTL
help
This provides a kernel interface for creating and updating z/VM APPLDATA
monitor records. The monitor records are updated at certain time

View File

@@ -50,7 +50,7 @@ static struct ratelimit_state bld_ratelimit;
static unsigned int sysctl_sld_mitigate = 1;
static DEFINE_SEMAPHORE(buslock_sem, 1);
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static const struct ctl_table sld_sysctls[] = {
{
.procname = "split_lock_mitigate",

View File

@@ -1572,7 +1572,7 @@ static int u2k_pipe_maxsz(const ulong *u_ptr, uint *k_ptr)
return proc_uint_u2k_conv_uop(u_ptr, k_ptr, round_pipe_size_ul);
}
static int do_proc_uint_conv_pipe_maxsz(ulong *u_ptr, uint *k_ptr,
static int do_proc_uint_conv_pipe_maxsz(bool *negp, ulong *u_ptr, uint *k_ptr,
int dir, const struct ctl_table *table)
{
return proc_uint_conv(u_ptr, k_ptr, dir, table, true,

View File

@@ -80,10 +80,9 @@ config PROC_VMCORE_DEVICE_RAM
Relevant architectures should select NEED_PROC_VMCORE_DEVICE_RAM.
config PROC_SYSCTL
config SYSCTL
bool "Sysctl support (/proc/sys)" if EXPERT
depends on PROC_FS
select SYSCTL
default y
help
The sysctl interface provides a means of dynamically changing

View File

@@ -29,7 +29,7 @@ proc-y += softirqs.o
proc-y += namespaces.o
proc-y += self.o
proc-y += thread_self.o
proc-$(CONFIG_PROC_SYSCTL) += proc_sysctl.o
proc-$(CONFIG_SYSCTL) += proc_sysctl.o
proc-$(CONFIG_NET) += proc_net.o
proc-$(CONFIG_PROC_KCORE) += kcore.o
proc-$(CONFIG_PROC_VMCORE) += vmcore.o

View File

@@ -351,7 +351,7 @@ extern void proc_thread_self_init(void);
/*
* proc_sysctl.c
*/
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
extern int proc_sys_init(void);
extern void proc_sys_evict_inode(struct inode *inode,
struct ctl_table_header *head);

View File

@@ -59,7 +59,7 @@ extern const int sysctl_vals[];
#define SYSCTL_LONG_ONE ((void *)&sysctl_long_vals[1])
#define SYSCTL_LONG_MAX ((void *)&sysctl_long_vals[2])
/**
/*
*
* "dir" originates from read_iter (dir = 0) or write_iter (dir = 1)
* in the file_operations struct at proc/proc_sysctl.c. Its value means
@@ -74,53 +74,108 @@ extern const int sysctl_vals[];
extern const unsigned long sysctl_long_vals[];
typedef int proc_handler(const struct ctl_table *ctl, int write, void *buffer,
size_t *lenp, loff_t *ppos);
int proc_dostring(const struct ctl_table *, int, void *, size_t *, loff_t *);
int proc_dobool(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
int proc_dointvec(const struct ctl_table *, int, void *, size_t *, loff_t *);
int proc_dointvec_minmax(const struct ctl_table *table, int dir, void *buffer,
typedef int proc_handler(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
int proc_dointvec_conv(const struct ctl_table *table, int dir, void *buffer,
/* proc_handler functions */
int proc_dostring(const struct ctl_table *ctl, int dir, void *buf, size_t *lenp,
loff_t *ppos);
int proc_dobool(const struct ctl_table *ctl, int dir, void *buf, size_t *lenp,
loff_t *ppos);
int proc_dointvec(const struct ctl_table *ctl, int dir, void *buf, size_t *lenp,
loff_t *ppos);
int proc_dointvec_minmax(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
int proc_douintvec(const struct ctl_table *ctl, int dir, void *buf, size_t *lenp,
loff_t *ppos);
int proc_douintvec_minmax(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
int proc_dou8vec_minmax(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
int proc_doulongvec_minmax(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
int proc_do_large_bitmap(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
int proc_do_static_key(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos);
/*
* proc_handler aggregators
*
* Create a proc_handler with a custom converter. Use when the user space
* value is a transformation of the kernel value. Cannot be passed as
* proc_handlers.
*
* Example of creating your custom proc handler:
* int custom_converter(bool *negp, ulong *u_ptr, uint *k_ptr,
* int dir, const struct ctl_table *ctl) {...}
* int custom_proc_handler(const struct ctl_table *ctl, int dir,
* void *buf, size_t *lenp, loff_t *ppos
* { return proc_dointvec_conv(ctl, dir, buf, lenp, ppos, custom_converter); }
*/
int proc_dointvec_conv(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
int dir, const struct ctl_table *table));
int proc_int_k2u_conv_kop(ulong *u_ptr, const int *k_ptr, bool *negp,
ulong (*k_ptr_op)(const ulong));
int proc_int_u2k_conv_uop(const ulong *u_ptr, int *k_ptr, const bool *negp,
ulong (*u_ptr_op)(const ulong));
int dir, const struct ctl_table *ctl));
int proc_douintvec_conv(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, ulong *u_ptr, uint *k_ptr,
int dir, const struct ctl_table *ctl));
int proc_doulongvec_conv(const struct ctl_table *ctl, int dir, void *buf,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, ulong *u_ptr, ulong *k_ptr,
int dir, const struct ctl_table *ctl));
/*
* bi-directional converter functions
*
* Specify the converter function for both directions (user to kernel & kernel
* to user). Use when you want to change the value of the variable before
* assignment. Used to create custom proc_handler aggregators.
*
* Example of creating your custom bi-directional converter:
* int custom_u2k(ulong *u_ptr, const uint *k_ptr) { ... }
* int custom_converter(bool *negp, ulong *u_ptr, uint *k_ptr,
* int dir, const struct ctl_table *ctl)
* { return proc_uint_conv(u_ptr, k_ptr, dir, ctl, true,
* custom_u2k, proc_uint_k2u_conv}
*/
int proc_int_conv(bool *negp, ulong *u_ptr, int *k_ptr, int dir,
const struct ctl_table *tbl, bool k_ptr_range_check,
int (*user_to_kern)(const bool *negp, const ulong *u_ptr, int *k_ptr),
int (*kern_to_user)(bool *negp, ulong *u_ptr, const int *k_ptr));
int proc_douintvec(const struct ctl_table *, int, void *, size_t *, loff_t *);
int proc_douintvec_minmax(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
int proc_douintvec_conv(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *lvalp, unsigned int *valp,
int write, const struct ctl_table *table));
int proc_uint_k2u_conv(ulong *u_ptr, const uint *k_ptr);
int proc_uint_u2k_conv_uop(const ulong *u_ptr, uint *k_ptr,
ulong (*u_ptr_op)(const ulong));
int proc_uint_conv(ulong *u_ptr, uint *k_ptr, int dir,
const struct ctl_table *tbl, bool k_ptr_range_check,
int (*user_to_kern)(const ulong *u_ptr, uint *k_ptr),
int (*kern_to_user)(ulong *u_ptr, const uint *k_ptr));
int proc_ulong_conv(ulong *u_ptr, ulong *k_ptr, int dir,
const struct ctl_table *tbl, bool k_ptr_range_check,
int (*user_to_kern)(const ulong *u_ptr, ulong *k_ptr),
int (*kern_to_user)(ulong *u_ptr, const ulong *k_ptr));
int proc_dou8vec_minmax(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
int proc_doulongvec_minmax(const struct ctl_table *, int, void *, size_t *, loff_t *);
int proc_doulongvec_minmax_conv(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
unsigned long convmul, unsigned long convdiv);
int proc_do_large_bitmap(const struct ctl_table *, int, void *, size_t *, loff_t *);
int proc_do_static_key(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos);
/*
* uni-directional converter functions
*
* Specify the converter function for one directions (user to kernel or
* kernel to user). Use to call the actual value conversion. Used to Create
* bi-directional converters.
*
* Example of creating a uni-directional converter:
* ulong op(const ulong val) { ... }
* int custom_unidir_conv(ulong *u_ptr, const uint *k_ptr)
* { return proc_uint_k2u_conv_kop(u_ptr, k_ptr, op); }
*/
int proc_int_k2u_conv_kop(ulong *u_ptr, const int *k_ptr, bool *negp,
ulong (*k_ptr_op)(const ulong));
int proc_int_u2k_conv_uop(const ulong *u_ptr, int *k_ptr, const bool *negp,
ulong (*u_ptr_op)(const ulong));
int proc_uint_k2u_conv(ulong *u_ptr, const uint *k_ptr);
int proc_uint_u2k_conv_uop(const ulong *u_ptr, uint *k_ptr,
ulong (*u_ptr_op)(const ulong));
int proc_ulong_u2k_conv_uop(const ulong *u_ptr, ulong *k_ptr,
ulong (*u_ptr_op)(const ulong));
int proc_ulong_k2u_conv_kop(ulong *u_ptr, const ulong *k_ptr,
ulong (*k_ptr_op)(const ulong));
/*
* Register a set of sysctl names by calling register_sysctl
@@ -190,9 +245,9 @@ struct ctl_node {
* @nreg: When nreg drops to 0 the ctl_table_header will be unregistered.
* @rcu: Delays the freeing of the inode. Introduced with "unfuck proc_sysctl ->d_compare()"
*
* @type: Enumeration to differentiate between ctl target types
* @type.SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
* @type.SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Identifies a permanently empty dir
* @type: Enumeration to differentiate between ctl target types:
* type.SYSCTL_TABLE_TYPE_DEFAULT: ctl target with no special considerations
* type.SYSCTL_TABLE_TYPE_PERMANENTLY_EMPTY: Identifies a permanently empty dir
* target to serve as a mount point
*/
struct ctl_table_header {

View File

@@ -18,7 +18,7 @@ enum uts_proc {
UTS_PROC_DOMAINNAME,
};
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
extern void uts_proc_notify(enum uts_proc proc);
#else
static inline void uts_proc_notify(enum uts_proc proc)

View File

@@ -1665,9 +1665,6 @@ config LD_ORPHAN_WARN_LEVEL
default "error" if WERROR
default "warn"
config SYSCTL
bool
config HAVE_UID16
bool

View File

@@ -54,7 +54,7 @@ void delayacct_init(void)
set_delayacct(delayacct_on);
}
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static int sysctl_delayacct(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{

View File

@@ -766,29 +766,6 @@ static struct ctl_table_root pid_table_root = {
.set_ownership = pid_table_root_set_ownership,
};
static int proc_do_cad_pid(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct pid *new_pid;
pid_t tmp_pid;
int r;
struct ctl_table tmp_table = *table;
tmp_pid = pid_vnr(cad_pid);
tmp_table.data = &tmp_pid;
r = proc_dointvec(&tmp_table, write, buffer, lenp, ppos);
if (r || !write)
return r;
new_pid = find_get_pid(tmp_pid);
if (!new_pid)
return -ESRCH;
put_pid(xchg(&cad_pid, new_pid));
return 0;
}
static const struct ctl_table pid_table[] = {
{
.procname = "pid_max",
@@ -799,14 +776,6 @@ static const struct ctl_table pid_table[] = {
.extra1 = &pid_max_min,
.extra2 = &pid_max_max,
},
#ifdef CONFIG_PROC_SYSCTL
{
.procname = "cad_pid",
.maxlen = sizeof(int),
.mode = 0600,
.proc_handler = proc_do_cad_pid,
},
#endif
};
#endif

View File

@@ -1366,6 +1366,29 @@ static struct attribute *reboot_attrs[] = {
};
#ifdef CONFIG_SYSCTL
static int proc_do_cad_pid(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
struct ctl_table tmp_table = *table;
struct pid *new_pid;
pid_t tmp_pid;
int r;
tmp_pid = pid_vnr(cad_pid);
tmp_table.data = &tmp_pid;
r = proc_dointvec(&tmp_table, write, buffer, lenp, ppos);
if (r || !write)
return r;
new_pid = find_get_pid(tmp_pid);
if (!new_pid)
return -ESRCH;
put_pid(xchg(&cad_pid, new_pid));
return 0;
}
static const struct ctl_table kern_reboot_table[] = {
{
.procname = "poweroff_cmd",
@@ -1381,6 +1404,12 @@ static const struct ctl_table kern_reboot_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "cad_pid",
.maxlen = sizeof(int),
.mode = 0600,
.proc_handler = proc_do_cad_pid,
},
};
static void __init kernel_reboot_sysctls_init(void)

View File

@@ -4638,7 +4638,7 @@ void set_numabalancing_state(bool enabled)
__set_numabalancing_state(enabled);
}
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static void reset_memory_tiering(void)
{
struct pglist_data *pgdat;
@@ -4674,7 +4674,7 @@ static int sysctl_numa_balancing(const struct ctl_table *table, int write,
}
return err;
}
#endif /* CONFIG_PROC_SYSCTL */
#endif /* CONFIG_SYSCTL */
#endif /* CONFIG_NUMA_BALANCING */
#ifdef CONFIG_SCHEDSTATS
@@ -4718,7 +4718,7 @@ static int __init setup_schedstats(char *str)
}
__setup("schedstats=", setup_schedstats);
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static int sysctl_schedstats(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos)
{
@@ -4738,7 +4738,7 @@ static int sysctl_schedstats(const struct ctl_table *table, int write, void *buf
set_schedstats(state);
return err;
}
#endif /* CONFIG_PROC_SYSCTL */
#endif /* CONFIG_SYSCTL */
#endif /* CONFIG_SCHEDSTATS */
#ifdef CONFIG_SYSCTL

View File

@@ -271,7 +271,7 @@ void rebuild_sched_domains_energy(void)
mutex_unlock(&sched_energy_mutex);
}
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static int sched_energy_aware_handler(const struct ctl_table *table, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
@@ -317,7 +317,7 @@ static int __init sched_energy_aware_sysctl_init(void)
}
late_initcall(sched_energy_aware_sysctl_init);
#endif /* CONFIG_PROC_SYSCTL */
#endif /* CONFIG_SYSCTL */
static void free_pd(struct perf_domain *pd)
{

View File

@@ -35,7 +35,7 @@ EXPORT_SYMBOL_GPL(sysctl_long_vals);
static const int ngroups_max = NGROUPS_MAX;
static const int cap_last_cap = CAP_LAST_CAP;
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
/**
* enum sysctl_writes_mode - supported sysctl write modes
@@ -64,14 +64,14 @@ enum sysctl_writes_mode {
};
static enum sysctl_writes_mode sysctl_writes_strict = SYSCTL_WRITES_STRICT;
#endif /* CONFIG_PROC_SYSCTL */
#endif /* CONFIG_SYSCTL */
#endif /* CONFIG_SYSCTL */
/*
* /proc/sys support
*/
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static int _proc_do_string(char *data, int maxlen, int dir,
char *buffer, size_t *lenp, loff_t *ppos)
@@ -148,7 +148,7 @@ static void warn_sysctl_write(const struct ctl_table *table)
* @ppos: file position
* @table: the sysctl table
*
* Returns true if the first position is non-zero and the sysctl_writes_strict
* Returns: true if the first position is non-zero and the sysctl_writes_strict
* mode indicates this is not allowed for numeric input types. String proc
* handlers can ignore the return value.
*/
@@ -184,7 +184,7 @@ static bool proc_first_pos_non_zero_ignore(loff_t *ppos,
* and a newline '\n' is added. It is truncated if the buffer is
* not large enough.
*
* Returns 0 on success.
* Returns: %0 on success.
*/
int proc_dostring(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos)
@@ -225,11 +225,14 @@ static void proc_skip_char(char **buf, size_t *size, const char v)
* @base: the base to use
* @res: where the parsed integer will be stored
*
* In case of success 0 is returned and @res will contain the parsed integer,
* @endp will hold any trailing characters.
* This function will fail the parse on overflow. If there wasn't an overflow
* the function will defer the decision what characters count as invalid to the
* caller.
*
* Returns:
* * %0 on success and @res will contain the parsed integer,
* @endp will hold any trailing characters.
* * %-ERANGE on overflow.
*/
static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
unsigned long *res)
@@ -263,10 +266,12 @@ static int strtoul_lenient(const char *cp, char **endp, unsigned int base,
* @perm_tr_len: size of the perm_tr vector
* @tr: pointer to store the trailer character
*
* In case of success %0 is returned and @buf and @size are updated with
* the amount of bytes read. If @tr is non-NULL and a trailing
* character exists (size is non-zero after returning from this
* function), @tr is updated with the trailing character.
* Returns:
* * %0 on success and @buf and @size are updated with
* the amount of bytes read. If @tr is non-NULL and a trailing
* character exists (size is non-zero after returning from this
* function), @tr is updated with the trailing character.
* * %-EINVAL on failure.
*/
static int proc_get_long(char **buf, size_t *size,
unsigned long *val, bool *neg,
@@ -365,7 +370,7 @@ static void proc_put_char(void **buf, size_t *size, char c)
* not NULL. Check that the values are less than UINT_MAX to avoid
* having to support wrap around from userspace.
*
* returns 0 on success.
* Returns: %0 on success.
*/
int proc_uint_u2k_conv_uop(const ulong *u_ptr, uint *k_ptr,
ulong (*u_ptr_op)(const ulong))
@@ -386,7 +391,7 @@ int proc_uint_u2k_conv_uop(const ulong *u_ptr, uint *k_ptr,
*
* Uses READ_ONCE to assign value to u_ptr.
*
* returns 0 on success.
* Returns: %0 on success.
*/
int proc_uint_k2u_conv(ulong *u_ptr, const uint *k_ptr)
{
@@ -409,7 +414,7 @@ int proc_uint_k2u_conv(ulong *u_ptr, const uint *k_ptr)
* When direction is kernel to user, then the u_ptr is modified.
* When direction is user to kernel, then the k_ptr is modified.
*
* Returns 0 on success
* Returns: %0 on success
*/
int proc_uint_conv(ulong *u_ptr, uint *k_ptr, int dir,
const struct ctl_table *tbl, bool k_ptr_range_check,
@@ -444,15 +449,15 @@ static int proc_uint_u2k_conv(const ulong *u_ptr, uint *k_ptr)
return proc_uint_u2k_conv_uop(u_ptr, k_ptr, NULL);
}
static int do_proc_uint_conv(ulong *u_ptr, uint *k_ptr, int dir,
static int do_proc_uint_conv(bool *negp, ulong *u_ptr, uint *k_ptr, int dir,
const struct ctl_table *tbl)
{
return proc_uint_conv(u_ptr, k_ptr, dir, tbl, false,
proc_uint_u2k_conv, proc_uint_k2u_conv);
}
static int do_proc_uint_conv_minmax(ulong *u_ptr, uint *k_ptr, int dir,
const struct ctl_table *tbl)
static int do_proc_uint_conv_minmax(bool *negp, ulong *u_ptr, uint *k_ptr,
int dir, const struct ctl_table *tbl)
{
return proc_uint_conv(u_ptr, k_ptr, dir, tbl, true,
proc_uint_u2k_conv, proc_uint_k2u_conv);
@@ -515,6 +520,23 @@ int proc_int_u2k_conv_uop(const ulong *u_ptr, int *k_ptr, const bool *negp,
return 0;
}
/**
* proc_int_conv - Change user or kernel pointer based on direction
*
* @negp: will be passed to uni-directional converters
* @u_ptr: pointer to user variable
* @k_ptr: pointer to kernel variable
* @dir: %TRUE if this is a write to the sysctl file
* @tbl: the sysctl table
* @k_ptr_range_check: Check range for k_ptr when %TRUE
* @user_to_kern: Callback used to assign value from user to kernel var
* @kern_to_user: Callback used to assign value from kernel to user var
*
* When direction is kernel to user, then the u_ptr is modified.
* When direction is user to kernel, then the k_ptr is modified.
*
* Returns: 0 on success
*/
int proc_int_conv(bool *negp, ulong *u_ptr, int *k_ptr, int dir,
const struct ctl_table *tbl, bool k_ptr_range_check,
int (*user_to_kern)(const bool *negp, const ulong *u_ptr, int *k_ptr),
@@ -572,14 +594,80 @@ static int do_proc_int_conv_minmax(bool *negp, unsigned long *u_ptr, int *k_ptr,
static const char proc_wspace_sep[] = { ' ', '\t', '\n' };
static int do_proc_dointvec(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
int dir, const struct ctl_table *table))
/*
* Element type processed by do_proc_vec(). The tag selects the element size
* and signedness, and it selects which member of union proc_vec_conv is live.
*/
enum proc_vec_type {
PROC_VEC_INT,
PROC_VEC_UINT,
PROC_VEC_ULONG,
};
/*
* Converter passed to do_proc_vec(). Only the member matching the
* enum proc_vec_type tag is ever read, so every dispatch stays fully typed and
* no void * converter pointer is needed.
*/
union proc_vec_conv {
int (*int_conv)(bool *negp, ulong *u_ptr, int *k_ptr,
int dir, const struct ctl_table *table);
int (*uint_conv)(bool *negp, ulong *u_ptr, uint *k_ptr,
int dir, const struct ctl_table *table);
int (*ulong_conv)(bool *negp, ulong *u_ptr, ulong *k_ptr,
int dir, const struct ctl_table *table);
};
/*
* Dispatch to the converter member selected by @type. @k_ptr walks
* table->data as raw bytes and is cast back to the element type here.
*/
static int proc_vec_conv(enum proc_vec_type type, union proc_vec_conv conv,
bool *negp, ulong *u_ptr, char *k_ptr, int dir,
const struct ctl_table *table)
{
int *i, vleft, first = 1, err = 0;
size_t left;
char *p;
switch (type) {
case PROC_VEC_INT:
return conv.int_conv(negp, u_ptr, (int *)k_ptr, dir, table);
case PROC_VEC_UINT:
return conv.uint_conv(negp, u_ptr, (uint *)k_ptr, dir, table);
case PROC_VEC_ULONG:
return conv.ulong_conv(negp, u_ptr, (ulong *)k_ptr, dir, table);
}
return -EINVAL;
}
/*
* Read/write a vector of @type elements. The element size and signedness are
* derived from @type, so a single runtime function replaces the per-type
* variants. table->data is walked as raw bytes (@i) advanced by @size; the
* converter performs the actual typed load/store.
*/
static int do_proc_vec(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
enum proc_vec_type type, union proc_vec_conv conv)
{
int vleft, first = 1, err = 0;
size_t left, size;
bool is_unsigned;
char *i, *p;
switch (type) {
case PROC_VEC_INT:
size = sizeof(int);
is_unsigned = false;
break;
case PROC_VEC_UINT:
size = sizeof(uint);
is_unsigned = true;
break;
case PROC_VEC_ULONG:
size = sizeof(ulong);
is_unsigned = true;
break;
default:
return -EINVAL;
}
if (!table->data || !table->maxlen || !*lenp ||
(*ppos && SYSCTL_KERN_TO_USER(dir))) {
@@ -587,12 +675,13 @@ static int do_proc_dointvec(const struct ctl_table *table, int dir,
return 0;
}
i = (int *) table->data;
vleft = table->maxlen / sizeof(*i);
i = table->data;
vleft = table->maxlen / size;
left = *lenp;
if (!conv)
conv = do_proc_int_conv;
/* uint arrays are not supported, *Do not* add support for them. */
if (type == PROC_VEC_UINT && vleft != 1)
return -EINVAL;
if (SYSCTL_USER_TO_KERN(dir)) {
if (proc_first_pos_non_zero_ignore(ppos, table))
@@ -603,9 +692,9 @@ static int do_proc_dointvec(const struct ctl_table *table, int dir,
p = buffer;
}
for (; left && vleft--; i++, first=0) {
for (; left && vleft--; i += size, first = 0) {
unsigned long lval;
bool neg;
bool neg = false;
if (SYSCTL_USER_TO_KERN(dir)) {
proc_skip_spaces(&p, &left);
@@ -613,16 +702,18 @@ static int do_proc_dointvec(const struct ctl_table *table, int dir,
if (!left)
break;
err = proc_get_long(&p, &left, &lval, &neg,
proc_wspace_sep,
sizeof(proc_wspace_sep), NULL);
proc_wspace_sep,
sizeof(proc_wspace_sep), NULL);
if (!err && neg && is_unsigned)
err = -EINVAL;
if (err)
break;
if (conv(&neg, &lval, i, 1, table)) {
if (proc_vec_conv(type, conv, &neg, &lval, i, dir, table)) {
err = -EINVAL;
break;
}
} else {
if (conv(&neg, &lval, i, 0, table)) {
if (proc_vec_conv(type, conv, &neg, &lval, i, dir, table)) {
err = -EINVAL;
break;
}
@@ -644,122 +735,6 @@ static int do_proc_dointvec(const struct ctl_table *table, int dir,
return err;
}
static int do_proc_douintvec_w(const struct ctl_table *table, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *u_ptr,
unsigned int *k_ptr, int dir,
const struct ctl_table *table))
{
unsigned long lval;
int err = 0;
size_t left;
bool neg;
char *p = buffer;
left = *lenp;
if (proc_first_pos_non_zero_ignore(ppos, table))
goto bail_early;
if (left > PAGE_SIZE - 1)
left = PAGE_SIZE - 1;
proc_skip_spaces(&p, &left);
if (!left) {
err = -EINVAL;
goto out_free;
}
err = proc_get_long(&p, &left, &lval, &neg,
proc_wspace_sep,
sizeof(proc_wspace_sep), NULL);
if (err || neg) {
err = -EINVAL;
goto out_free;
}
if (conv(&lval, (unsigned int *) table->data, 1, table)) {
err = -EINVAL;
goto out_free;
}
if (!err && left)
proc_skip_spaces(&p, &left);
out_free:
if (err)
return -EINVAL;
return 0;
bail_early:
*ppos += *lenp;
return err;
}
static int do_proc_douintvec_r(const struct ctl_table *table, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *u_ptr,
unsigned int *k_ptr, int dir,
const struct ctl_table *table))
{
unsigned long lval;
int err = 0;
size_t left;
left = *lenp;
if (conv(&lval, (unsigned int *) table->data, 0, table)) {
err = -EINVAL;
goto out;
}
proc_put_long(&buffer, &left, lval, false);
if (!left)
goto out;
proc_put_char(&buffer, &left, '\n');
out:
*lenp -= left;
*ppos += *lenp;
return err;
}
static int do_proc_douintvec(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *u_ptr,
unsigned int *k_ptr, int dir,
const struct ctl_table *table))
{
unsigned int vleft;
if (!table->data || !table->maxlen || !*lenp ||
(*ppos && SYSCTL_KERN_TO_USER(dir))) {
*lenp = 0;
return 0;
}
vleft = table->maxlen / sizeof(unsigned int);
/*
* Arrays are not supported, keep this simple. *Do not* add
* support for them.
*/
if (vleft != 1) {
*lenp = 0;
return -EINVAL;
}
if (!conv)
conv = do_proc_uint_conv;
if (SYSCTL_USER_TO_KERN(dir))
return do_proc_douintvec_w(table, buffer, lenp, ppos, conv);
return do_proc_douintvec_r(table, buffer, lenp, ppos, conv);
}
/**
* proc_douintvec_conv - read a vector of unsigned ints with a custom converter
*
@@ -774,14 +749,19 @@ static int do_proc_douintvec(const struct ctl_table *table, int dir,
* values from/to the user buffer, treated as an ASCII string. Negative
* strings are not allowed.
*
* Returns 0 on success
* Returns: %0 on success
*/
int proc_douintvec_conv(const struct ctl_table *table, int dir, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *u_ptr, unsigned int *k_ptr,
int (*conv)(bool *negp, ulong *u_ptr, uint *k_ptr,
int dir, const struct ctl_table *table))
{
return do_proc_douintvec(table, dir, buffer, lenp, ppos, conv);
if (!conv)
conv = do_proc_uint_conv;
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_UINT,
(union proc_vec_conv){ .uint_conv = conv });
}
/**
@@ -798,7 +778,7 @@ int proc_douintvec_conv(const struct ctl_table *table, int dir, void *buffer,
* table->data must point to a bool variable and table->maxlen must
* be sizeof(bool).
*
* Returns 0 on success.
* Returns: %0 on success.
*/
int proc_dobool(const struct ctl_table *table, int dir, void *buffer,
size_t *lenp, loff_t *ppos)
@@ -835,12 +815,13 @@ int proc_dobool(const struct ctl_table *table, int dir, void *buffer,
* Reads/writes up to table->maxlen/sizeof(unsigned int) integer
* values from/to the user buffer, treated as an ASCII string.
*
* Returns 0 on success.
* Returns: %0 on success.
*/
int proc_dointvec(const struct ctl_table *table, int dir, void *buffer,
size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table, dir, buffer, lenp, ppos, NULL);
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_INT,
(union proc_vec_conv){ .int_conv = do_proc_int_conv });
}
/**
@@ -854,13 +835,13 @@ int proc_dointvec(const struct ctl_table *table, int dir, void *buffer,
* Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
* values from/to the user buffer, treated as an ASCII string.
*
* Returns 0 on success.
* Returns: %0 on success.
*/
int proc_douintvec(const struct ctl_table *table, int dir, void *buffer,
size_t *lenp, loff_t *ppos)
{
return do_proc_douintvec(table, dir, buffer, lenp, ppos,
do_proc_uint_conv);
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_UINT,
(union proc_vec_conv){ .uint_conv = do_proc_uint_conv });
}
/**
@@ -877,14 +858,14 @@ int proc_douintvec(const struct ctl_table *table, int dir, void *buffer,
* This routine will ensure the values are within the range specified by
* table->extra1 (min) and table->extra2 (max).
*
* Returns 0 on success or -EINVAL when the range check fails and
* Returns: %0 on success or -EINVAL when the range check fails and
* SYSCTL_USER_TO_KERN(dir) == true
*/
int proc_dointvec_minmax(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_dointvec(table, dir, buffer, lenp, ppos,
do_proc_int_conv_minmax);
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_INT,
(union proc_vec_conv){ .int_conv = do_proc_int_conv_minmax });
}
/**
@@ -904,14 +885,14 @@ int proc_dointvec_minmax(const struct ctl_table *table, int dir,
* (max). And Check that the values are less than UINT_MAX to avoid having to
* support wrap around uses from userspace.
*
* Returns 0 on success or -ERANGE when range check failes and
* Returns: %0 on success or -ERANGE when range check failes and
* SYSCTL_USER_TO_KERN(dir) == true
*/
int proc_douintvec_minmax(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos)
{
return do_proc_douintvec(table, dir, buffer, lenp, ppos,
do_proc_uint_conv_minmax);
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_UINT,
(union proc_vec_conv){ .uint_conv = do_proc_uint_conv_minmax });
}
/**
@@ -929,7 +910,7 @@ int proc_douintvec_minmax(const struct ctl_table *table, int dir,
* This routine will ensure the values are within the range specified by
* table->extra1 (min) and table->extra2 (max).
*
* Returns 0 on success or an error on SYSCTL_USER_TO_KERN(dir) == true
* Returns: %0 on success or an error on SYSCTL_USER_TO_KERN(dir) == true
* and the range check fails.
*/
int proc_dou8vec_minmax(const struct ctl_table *table, int dir,
@@ -954,8 +935,8 @@ int proc_dou8vec_minmax(const struct ctl_table *table, int dir,
tmp.extra2 = (unsigned int *) &max;
val = READ_ONCE(*data);
res = do_proc_douintvec(&tmp, dir, buffer, lenp, ppos,
do_proc_uint_conv_minmax);
res = do_proc_vec(&tmp, dir, buffer, lenp, ppos, PROC_VEC_UINT,
(union proc_vec_conv){ .uint_conv = do_proc_uint_conv_minmax });
if (res)
return res;
if (SYSCTL_USER_TO_KERN(dir))
@@ -964,87 +945,129 @@ int proc_dou8vec_minmax(const struct ctl_table *table, int dir,
}
EXPORT_SYMBOL_GPL(proc_dou8vec_minmax);
static int do_proc_doulongvec_minmax(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
unsigned long convmul,
unsigned long convdiv)
/**
* proc_ulong_conv - Change user or kernel pointer based on direction
*
* @u_ptr: pointer to user variable
* @k_ptr: pointer to kernel variable
* @dir: %TRUE if this is a write to the sysctl file
* @tbl: the sysctl table
* @k_ptr_range_check: Check range for k_ptr when %TRUE
* @user_to_kern: Callback used to assign value from user to kernel var
* @kern_to_user: Callback used to assign value from kernel to user var
*
* When direction is kernel to user, then the u_ptr is modified.
* When direction is user to kernel, then the k_ptr is modified.
*
* Returns: 0 on success
*/
int proc_ulong_conv(ulong *u_ptr, ulong *k_ptr, int dir,
const struct ctl_table *tbl, bool k_ptr_range_check,
int (*user_to_kern)(const ulong *u_ptr, ulong *k_ptr),
int (*kern_to_user)(ulong *u_ptr, const ulong *k_ptr))
{
unsigned long *i, *min, *max;
int vleft, first = 1, err = 0;
size_t left;
char *p;
if (SYSCTL_KERN_TO_USER(dir))
return kern_to_user(u_ptr, k_ptr);
if (!table->data || !table->maxlen || !*lenp ||
(*ppos && SYSCTL_KERN_TO_USER(dir))) {
*lenp = 0;
return 0;
}
if (k_ptr_range_check) {
ulong tmp_k;
int ret;
i = table->data;
min = table->extra1;
max = table->extra2;
vleft = table->maxlen / sizeof(unsigned long);
left = *lenp;
if (SYSCTL_USER_TO_KERN(dir)) {
if (proc_first_pos_non_zero_ignore(ppos, table))
goto out;
if (left > PAGE_SIZE - 1)
left = PAGE_SIZE - 1;
p = buffer;
}
for (; left && vleft--; i++, first = 0) {
unsigned long val;
if (SYSCTL_USER_TO_KERN(dir)) {
bool neg;
proc_skip_spaces(&p, &left);
if (!left)
break;
err = proc_get_long(&p, &left, &val, &neg,
proc_wspace_sep,
sizeof(proc_wspace_sep), NULL);
if (err || neg) {
err = -EINVAL;
break;
}
val = convmul * val / convdiv;
if ((min && val < *min) || (max && val > *max)) {
err = -EINVAL;
break;
}
WRITE_ONCE(*i, val);
} else {
val = convdiv * READ_ONCE(*i) / convmul;
if (!first)
proc_put_char(&buffer, &left, '\t');
proc_put_long(&buffer, &left, val, false);
}
}
if (SYSCTL_KERN_TO_USER(dir) && !first && left && !err)
proc_put_char(&buffer, &left, '\n');
if (SYSCTL_USER_TO_KERN(dir) && !err)
proc_skip_spaces(&p, &left);
if (SYSCTL_USER_TO_KERN(dir) && first)
return err ? : -EINVAL;
*lenp -= left;
out:
*ppos += *lenp;
return err;
if (!tbl)
return -EINVAL;
ret = user_to_kern(u_ptr, &tmp_k);
if (ret)
return ret;
if ((tbl->extra1 && *(ulong *)tbl->extra1 > tmp_k) ||
(tbl->extra2 && *(ulong *)tbl->extra2 < tmp_k))
return -ERANGE;
WRITE_ONCE(*k_ptr, tmp_k);
} else
return user_to_kern(u_ptr, k_ptr);
return 0;
}
int proc_doulongvec_minmax_conv(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
unsigned long convmul, unsigned long convdiv)
/**
* proc_ulong_u2k_conv_uop - Assign user value to a kernel pointer
*
* @u_ptr: pointer to user space variable
* @k_ptr: pointer to kernel variable
* @u_ptr_op: execute this function before assigning to k_ptr
*
* Uses WRITE_ONCE to assign value to k_ptr. Executes u_ptr_op if
* not NULL.
*
* Returns: 0 on success.
*/
int proc_ulong_u2k_conv_uop(const ulong *u_ptr, ulong *k_ptr,
ulong (*u_ptr_op)(const ulong))
{
return do_proc_doulongvec_minmax(table, dir, buffer, lenp, ppos,
convmul, convdiv);
ulong u = u_ptr_op ? u_ptr_op(*u_ptr) : *u_ptr;
WRITE_ONCE(*k_ptr, u);
return 0;
}
static int proc_ulong_u2k_conv(const ulong *u_ptr, ulong *k_ptr)
{
return proc_ulong_u2k_conv_uop(u_ptr, k_ptr, NULL);
}
/**
* proc_ulong_k2u_conv_kop - Assign kernel value to a user space pointer
*
* @u_ptr: pointer to user space variable
* @k_ptr: pointer to kernel variable
* @k_ptr_op: Operation applied to k_ptr before assignment
*
* Uses READ_ONCE to assign value to u_ptr. Executes k_ptr_op if
* not NULL.
*
* Returns: 0 on success.
*/
int proc_ulong_k2u_conv_kop(ulong *u_ptr, const ulong *k_ptr,
ulong (*k_ptr_op)(const ulong))
{
ulong val = k_ptr_op ? k_ptr_op(READ_ONCE(*k_ptr)) : READ_ONCE(*k_ptr);
*u_ptr = (ulong)val;
return 0;
}
static int proc_ulong_k2u_conv(ulong *u_ptr, const ulong *k_ptr)
{
return proc_ulong_k2u_conv_kop(u_ptr, k_ptr, NULL);
}
static int do_proc_ulong_conv(bool *negp, ulong *u_ptr, ulong *k_ptr, int dir,
const struct ctl_table *tbl)
{
return proc_ulong_conv(u_ptr, k_ptr, dir, tbl, true,
proc_ulong_u2k_conv, proc_ulong_k2u_conv);
}
/**
* proc_doulongvec_conv - read a vector of unsigned longs with a custom converter
*
* @table: the sysctl table
* @dir: %TRUE if this is a write to the sysctl file
* @buffer: the user buffer
* @lenp: the size of the user buffer
* @ppos: file position
* @conv: Custom converter call back
*
* Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
* values from/to the user buffer, treated as an ASCII string. Negative
* strings are not allowed.
*
* Returns: 0 on success
*/
int proc_doulongvec_conv(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, ulong *u_ptr, ulong *k_ptr,
int dir, const struct ctl_table *table))
{
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_ULONG,
(union proc_vec_conv){ .ulong_conv = conv });
}
/**
@@ -1061,12 +1084,13 @@ int proc_doulongvec_minmax_conv(const struct ctl_table *table, int dir,
* This routine will ensure the values are within the range specified by
* table->extra1 (min) and table->extra2 (max).
*
* Returns 0 on success.
* Returns: %0 on success.
*/
int proc_doulongvec_minmax(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos)
{
return proc_doulongvec_minmax_conv(table, dir, buffer, lenp, ppos, 1l, 1l);
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_ULONG,
(union proc_vec_conv){ .ulong_conv = do_proc_ulong_conv });
}
/**
@@ -1076,21 +1100,22 @@ int proc_doulongvec_minmax(const struct ctl_table *table, int dir,
* @buffer: the user buffer
* @lenp: the size of the user buffer
* @ppos: file position
* @conv: Custom converter call back
* @conv: Custom converter call back. Defaults to do_proc_int_conv
*
* Reads/writes up to table->maxlen/sizeof(unsigned int) unsigned integer
* values from/to the user buffer, treated as an ASCII string. Negative
* strings are not allowed.
* Reads/writes up to table->maxlen/sizeof(int) integer values from/to the
* user buffer, treated as an ASCII string.
*
* Returns: 0 on success
*/
int proc_dointvec_conv(const struct ctl_table *table, int dir, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(bool *negp, unsigned long *u_ptr, int *k_ptr,
int dir, const struct ctl_table *table))
{
return do_proc_dointvec(table, dir, buffer, lenp, ppos, conv);
if (!conv)
conv = do_proc_int_conv;
return do_proc_vec(table, dir, buffer, lenp, ppos, PROC_VEC_INT,
(union proc_vec_conv){ .int_conv = conv });
}
/**
@@ -1108,7 +1133,7 @@ int proc_dointvec_conv(const struct ctl_table *table, int dir, void *buffer,
* large bitmaps may be represented in a compact manner. Writing into
* the file will clear the bitmap then update it with the given input.
*
* Returns 0 on success.
* Returns: %0 on success.
*/
int proc_do_large_bitmap(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos)
@@ -1240,7 +1265,7 @@ int proc_do_large_bitmap(const struct ctl_table *table, int dir,
return err;
}
#else /* CONFIG_PROC_SYSCTL */
#else /* CONFIG_SYSCTL */
int proc_dostring(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos)
@@ -1280,7 +1305,7 @@ int proc_douintvec_minmax(const struct ctl_table *table, int dir,
int proc_douintvec_conv(const struct ctl_table *table, int write, void *buffer,
size_t *lenp, loff_t *ppos,
int (*conv)(unsigned long *lvalp, unsigned int *valp,
int (*conv)(bool *negp, ulong *lvalp, uint *valp,
int write, const struct ctl_table *table))
{
return -ENOSYS;
@@ -1317,9 +1342,10 @@ int proc_doulongvec_minmax(const struct ctl_table *table, int dir,
return -ENOSYS;
}
int proc_doulongvec_minmax_conv(const struct ctl_table *table, int dir,
int proc_doulongvec_conv(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos,
unsigned long convmul, unsigned long convdiv)
int (*conv)(bool *negp, ulong *u_ptr, ulong *k_ptr,
int dir, const struct ctl_table *table))
{
return -ENOSYS;
}
@@ -1338,7 +1364,7 @@ int proc_do_large_bitmap(const struct ctl_table *table, int dir,
return -ENOSYS;
}
#endif /* CONFIG_PROC_SYSCTL */
#endif /* CONFIG_SYSCTL */
#if defined(CONFIG_SYSCTL)
int proc_do_static_key(const struct ctl_table *table, int dir,
@@ -1372,7 +1398,7 @@ int proc_do_static_key(const struct ctl_table *table, int dir,
}
static const struct ctl_table sysctl_subsys_table[] = {
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
{
.procname = "sysctl_writes_strict",
.data = &sysctl_writes_strict,

View File

@@ -98,7 +98,7 @@ void __init register_refined_jiffies(long cycles_per_second)
__clocksource_register(&refined_jiffies);
}
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static ulong mult_hz(const ulong val)
{
return val * HZ;
@@ -185,7 +185,24 @@ static int do_proc_int_conv_ms_jiffies_minmax(bool *negp, ulong *u_ptr,
sysctl_u2k_int_conv_ms, sysctl_k2u_int_conv_ms);
}
#else // CONFIG_PROC_SYSCTL
static int sysctl_u2k_ulong_conv_ms(const ulong *u_ptr, ulong *k_ptr)
{
return proc_ulong_u2k_conv_uop(u_ptr, k_ptr, sysctl_msecs_to_jiffies);
}
static int sysctl_k2u_ulong_conv_ms(ulong *u_ptr, const ulong *k_ptr)
{
return proc_ulong_k2u_conv_kop(u_ptr, k_ptr, sysctl_jiffies_to_msecs);
}
static int do_proc_ulong_conv_ms_jiffies(bool *negp, ulong *u_ptr, ulong *k_ptr,
int dir, const struct ctl_table *tbl)
{
return proc_ulong_conv(u_ptr, k_ptr, dir, tbl, false,
sysctl_u2k_ulong_conv_ms, sysctl_k2u_ulong_conv_ms);
}
#else // CONFIG_SYSCTL
static int do_proc_int_conv_jiffies(bool *negp, ulong *u_ptr, int *k_ptr,
int dir, const struct ctl_table *tbl)
{
@@ -211,6 +228,12 @@ static int do_proc_int_conv_ms_jiffies_minmax(bool *negp, ulong *u_ptr,
{
return -ENOSYS;
}
static int do_proc_ulong_conv_ms_jiffies(bool *negp, ulong *u_ptr, ulong *k_ptr,
int dir, const struct ctl_table *tbl)
{
return -ENOSYS;
}
#endif
/**
@@ -309,8 +332,8 @@ int proc_dointvec_ms_jiffies_minmax(const struct ctl_table *table, int dir,
int proc_doulongvec_ms_jiffies_minmax(const struct ctl_table *table, int dir,
void *buffer, size_t *lenp, loff_t *ppos)
{
return proc_doulongvec_minmax_conv(table, dir, buffer, lenp, ppos,
HZ, 1000l);
return proc_doulongvec_conv(table, dir, buffer, lenp, ppos,
do_proc_ulong_conv_ms_jiffies);
}
EXPORT_SYMBOL(proc_doulongvec_ms_jiffies_minmax);

View File

@@ -13,7 +13,7 @@
#include <linux/wait.h>
#include <linux/rwsem.h>
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
static void *get_uts(const struct ctl_table *table)
{
@@ -122,7 +122,7 @@ static const struct ctl_table uts_kern_table[] = {
},
};
#ifdef CONFIG_PROC_SYSCTL
#ifdef CONFIG_SYSCTL
/*
* Notify userspace about a change in a certain entry of uts_kern_table,
* identified by the parameter proc.

View File

@@ -2710,7 +2710,7 @@ config TEST_FIRMWARE
config TEST_SYSCTL
tristate "sysctl test driver"
depends on PROC_SYSCTL
depends on SYSCTL
help
This builds the "test_sysctl" module. This driver enables to test the
proc sysctl interfaces available to drivers safely without affecting

View File

@@ -7,7 +7,7 @@
/*
* This module provides an interface to the proc sysctl interfaces. This
* driver requires CONFIG_PROC_SYSCTL. It will not normally be loaded by the
* driver requires CONFIG_SYSCTL. It will not normally be loaded by the
* system unless explicitly requested by name. You can also build this driver
* into your kernel.
*/

View File

@@ -26,7 +26,7 @@ config NET_MPLS_GSO
config MPLS_ROUTING
tristate "MPLS: routing support"
depends on NET_IP_TUNNEL || NET_IP_TUNNEL=n
depends on PROC_SYSCTL
depends on SYSCTL
help
Add support for forwarding of mpls packets.

View File

@@ -118,7 +118,7 @@ CONFIG_NFT_NAT=m
CONFIG_NUMA=y
CONFIG_OPENVSWITCH=m
CONFIG_PAGE_POOL_STATS=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSCTL=y
CONFIG_PSAMPLE=m
CONFIG_RPS=y
CONFIG_SYN_COOKIES=y

View File

@@ -4,7 +4,7 @@ CONFIG_IPV6=y
CONFIG_NET_NS=y
CONFIG_NET_SCH_FIFO=y
CONFIG_NET_SCH_FQ=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSCTL=y
CONFIG_SYN_COOKIES=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_MD5SIG=y

View File

@@ -63,7 +63,7 @@ CONFIG_FILE_LOCKING=y
CONFIG_POSIX_TIMERS=y
CONFIG_DEVTMPFS=y
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_SYSCTL=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_CONSOLE_LOGLEVEL_DEFAULT=15