mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 18:03:10 -04:00
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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -1665,9 +1665,6 @@ config LD_ORPHAN_WARN_LEVEL
|
||||
default "error" if WERROR
|
||||
default "warn"
|
||||
|
||||
config SYSCTL
|
||||
bool
|
||||
|
||||
config HAVE_UID16
|
||||
bool
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
31
kernel/pid.c
31
kernel/pid.c
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
542
kernel/sysctl.c
542
kernel/sysctl.c
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user