You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
sysctl: pass kernel pointers to ->proc_handler
Instead of having all the sysctl handlers deal with user pointers, which is rather hairy in terms of the BPF interaction, copy the input to and from userspace in common code. This also means that the strings are always NUL-terminated by the common code, making the API a little bit safer. As most handler just pass through the data to one of the common handlers a lot of the changes are mechnical. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Andrey Ignatov <rdna@fb.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
committed by
Al Viro
parent
f461d2dcd5
commit
32927393dc
@@ -203,7 +203,7 @@ static void __init register_insn_emulation(struct insn_emulation_ops *ops)
|
||||
}
|
||||
|
||||
static int emulation_proc_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
void *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
@@ -341,8 +341,7 @@ static unsigned int find_supported_vector_length(unsigned int vl)
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
||||
static int sve_proc_do_default_vl(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
int vl = sve_default_vl;
|
||||
|
||||
@@ -95,16 +95,15 @@ int proc_lasat_ip(struct ctl_table *table, int write,
|
||||
len = 0;
|
||||
p = buffer;
|
||||
while (len < *lenp) {
|
||||
if (get_user(c, p++))
|
||||
return -EFAULT;
|
||||
c = *p;
|
||||
p++;
|
||||
if (c == 0 || c == '\n')
|
||||
break;
|
||||
len++;
|
||||
}
|
||||
if (len >= sizeof(ipbuf)-1)
|
||||
len = sizeof(ipbuf) - 1;
|
||||
if (copy_from_user(ipbuf, buffer, len))
|
||||
return -EFAULT;
|
||||
memcpy(ipbuf, buffer, len);
|
||||
ipbuf[len] = 0;
|
||||
*ppos += *lenp;
|
||||
/* Now see if we can convert it to a valid IP */
|
||||
@@ -122,11 +121,9 @@ int proc_lasat_ip(struct ctl_table *table, int write,
|
||||
if (len > *lenp)
|
||||
len = *lenp;
|
||||
if (len)
|
||||
if (copy_to_user(buffer, ipbuf, len))
|
||||
return -EFAULT;
|
||||
memcpy(buffer, ipbuf, len);
|
||||
if (len < *lenp) {
|
||||
if (put_user('\n', ((char *) buffer) + len))
|
||||
return -EFAULT;
|
||||
*((char *)buffer + len) = '\n';
|
||||
len++;
|
||||
}
|
||||
*lenp = len;
|
||||
|
||||
@@ -51,10 +51,9 @@ static struct platform_device *appldata_pdev;
|
||||
*/
|
||||
static const char appldata_proc_name[APPLDATA_PROC_NAME_LENGTH] = "appldata";
|
||||
static int appldata_timer_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos);
|
||||
void *buffer, size_t *lenp, loff_t *ppos);
|
||||
static int appldata_interval_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer,
|
||||
size_t *lenp, loff_t *ppos);
|
||||
void *buffer, size_t *lenp, loff_t *ppos);
|
||||
|
||||
static struct ctl_table_header *appldata_sysctl_header;
|
||||
static struct ctl_table appldata_table[] = {
|
||||
@@ -217,7 +216,7 @@ static void __appldata_vtimer_setup(int cmd)
|
||||
*/
|
||||
static int
|
||||
appldata_timer_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int timer_active = appldata_timer_active;
|
||||
int rc;
|
||||
@@ -250,7 +249,7 @@ appldata_timer_handler(struct ctl_table *ctl, int write,
|
||||
*/
|
||||
static int
|
||||
appldata_interval_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int interval = appldata_interval;
|
||||
int rc;
|
||||
@@ -280,7 +279,7 @@ appldata_interval_handler(struct ctl_table *ctl, int write,
|
||||
*/
|
||||
static int
|
||||
appldata_generic_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct appldata_ops *ops = NULL, *tmp_ops;
|
||||
struct list_head *lh;
|
||||
|
||||
@@ -867,7 +867,7 @@ static int debug_active = 1;
|
||||
* if debug_active is already off
|
||||
*/
|
||||
static int s390dbf_procactive(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
if (!write || debug_stoppable || !debug_active)
|
||||
return proc_dointvec(table, write, buffer, lenp, ppos);
|
||||
|
||||
@@ -594,7 +594,7 @@ static int __init topology_setup(char *str)
|
||||
early_param("topology", topology_setup);
|
||||
|
||||
static int topology_ctl_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int enabled = topology_is_enabled();
|
||||
int new_mode;
|
||||
|
||||
@@ -245,7 +245,7 @@ static int cmm_skip_blanks(char *cp, char **endp)
|
||||
}
|
||||
|
||||
static int cmm_pages_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
long nr = cmm_get_pages();
|
||||
struct ctl_table ctl_entry = {
|
||||
@@ -264,7 +264,7 @@ static int cmm_pages_handler(struct ctl_table *ctl, int write,
|
||||
}
|
||||
|
||||
static int cmm_timed_pages_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
void *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
long nr = cmm_get_timed_pages();
|
||||
@@ -284,7 +284,7 @@ static int cmm_timed_pages_handler(struct ctl_table *ctl, int write,
|
||||
}
|
||||
|
||||
static int cmm_timeout_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
char buf[64], *p;
|
||||
long nr, seconds;
|
||||
@@ -297,8 +297,7 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write,
|
||||
|
||||
if (write) {
|
||||
len = min(*lenp, sizeof(buf));
|
||||
if (copy_from_user(buf, buffer, len))
|
||||
return -EFAULT;
|
||||
memcpy(buf, buffer, len);
|
||||
buf[len - 1] = '\0';
|
||||
cmm_skip_blanks(buf, &p);
|
||||
nr = simple_strtoul(p, &p, 0);
|
||||
@@ -311,8 +310,7 @@ static int cmm_timeout_handler(struct ctl_table *ctl, int write,
|
||||
cmm_timeout_pages, cmm_timeout_seconds);
|
||||
if (len > *lenp)
|
||||
len = *lenp;
|
||||
if (copy_to_user(buffer, buf, len))
|
||||
return -EFAULT;
|
||||
memcpy(buffer, buf, len);
|
||||
*lenp = len;
|
||||
*ppos += len;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,7 @@ static bool __read_mostly sched_itmt_capable;
|
||||
unsigned int __read_mostly sysctl_sched_itmt_enabled;
|
||||
|
||||
static int sched_itmt_update_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
unsigned int old_sysctl;
|
||||
int ret;
|
||||
|
||||
@@ -3631,7 +3631,7 @@ static void cdrom_update_settings(void)
|
||||
}
|
||||
|
||||
static int cdrom_sysctl_handler(struct ctl_table *ctl, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -2057,7 +2057,7 @@ static char sysctl_bootid[16];
|
||||
* sysctl system call, as 16 bytes of binary data.
|
||||
*/
|
||||
static int proc_do_uuid(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct ctl_table fake_table;
|
||||
unsigned char buf[64], tmp_uuid[16], *uuid;
|
||||
|
||||
@@ -183,8 +183,7 @@ static void mac_hid_stop_emulation(void)
|
||||
}
|
||||
|
||||
static int mac_hid_toggle_emumouse(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp,
|
||||
loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
int *valp = table->data;
|
||||
int old_val = *valp;
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#define PARPORT_MAX_SPINTIME_VALUE 1000
|
||||
|
||||
static int do_active_device(struct ctl_table *table, int write,
|
||||
void __user *result, size_t *lenp, loff_t *ppos)
|
||||
void *result, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct parport *port = (struct parport *)table->extra1;
|
||||
char buffer[256];
|
||||
@@ -65,13 +65,13 @@ static int do_active_device(struct ctl_table *table, int write,
|
||||
*lenp = len;
|
||||
|
||||
*ppos += len;
|
||||
|
||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||
memcpy(result, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PARPORT_1284
|
||||
static int do_autoprobe(struct ctl_table *table, int write,
|
||||
void __user *result, size_t *lenp, loff_t *ppos)
|
||||
void *result, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct parport_device_info *info = table->extra2;
|
||||
const char *str;
|
||||
@@ -108,13 +108,13 @@ static int do_autoprobe(struct ctl_table *table, int write,
|
||||
|
||||
*ppos += len;
|
||||
|
||||
return copy_to_user (result, buffer, len) ? -EFAULT : 0;
|
||||
memcpy(result, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
#endif /* IEEE1284.3 support. */
|
||||
|
||||
static int do_hardware_base_addr(struct ctl_table *table, int write,
|
||||
void __user *result,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
void *result, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct parport *port = (struct parport *)table->extra1;
|
||||
char buffer[20];
|
||||
@@ -136,13 +136,12 @@ static int do_hardware_base_addr(struct ctl_table *table, int write,
|
||||
*lenp = len;
|
||||
|
||||
*ppos += len;
|
||||
|
||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||
memcpy(result, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_hardware_irq(struct ctl_table *table, int write,
|
||||
void __user *result,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
void *result, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct parport *port = (struct parport *)table->extra1;
|
||||
char buffer[20];
|
||||
@@ -164,13 +163,12 @@ static int do_hardware_irq(struct ctl_table *table, int write,
|
||||
*lenp = len;
|
||||
|
||||
*ppos += len;
|
||||
|
||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||
memcpy(result, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_hardware_dma(struct ctl_table *table, int write,
|
||||
void __user *result,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
void *result, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct parport *port = (struct parport *)table->extra1;
|
||||
char buffer[20];
|
||||
@@ -192,13 +190,12 @@ static int do_hardware_dma(struct ctl_table *table, int write,
|
||||
*lenp = len;
|
||||
|
||||
*ppos += len;
|
||||
|
||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||
memcpy(result, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_hardware_modes(struct ctl_table *table, int write,
|
||||
void __user *result,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
void *result, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct parport *port = (struct parport *)table->extra1;
|
||||
char buffer[40];
|
||||
@@ -231,8 +228,8 @@ static int do_hardware_modes(struct ctl_table *table, int write,
|
||||
*lenp = len;
|
||||
|
||||
*ppos += len;
|
||||
|
||||
return copy_to_user(result, buffer, len) ? -EFAULT : 0;
|
||||
memcpy(result, buffer, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define PARPORT_PORT_DIR(CHILD) { .procname = NULL, .mode = 0555, .child = CHILD }
|
||||
|
||||
@@ -165,7 +165,7 @@ static long get_nr_dentry_negative(void)
|
||||
return sum < 0 ? 0 : sum;
|
||||
}
|
||||
|
||||
int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,
|
||||
int proc_nr_dentry(struct ctl_table *table, int write, void *buffer,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
dentry_stat.nr_dentry = get_nr_dentry();
|
||||
|
||||
@@ -47,7 +47,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
|
||||
}
|
||||
|
||||
int drop_caches_sysctl_handler(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *length, loff_t *ppos)
|
||||
void *buffer, size_t *length, loff_t *ppos)
|
||||
{
|
||||
int ret;
|
||||
|
||||
|
||||
@@ -80,14 +80,14 @@ EXPORT_SYMBOL_GPL(get_max_files);
|
||||
*/
|
||||
#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
|
||||
int proc_nr_files(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
files_stat.nr_files = get_nr_files();
|
||||
return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
|
||||
}
|
||||
#else
|
||||
int proc_nr_files(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
@@ -51,8 +51,7 @@ static unsigned fscache_op_max_active = 2;
|
||||
static struct ctl_table_header *fscache_sysctl_header;
|
||||
|
||||
static int fscache_max_active_sysctl(struct ctl_table *table, int write,
|
||||
void __user *buffer,
|
||||
size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
struct workqueue_struct **wqp = table->extra1;
|
||||
unsigned int *datap = table->data;
|
||||
|
||||
@@ -108,7 +108,7 @@ long get_nr_dirty_inodes(void)
|
||||
*/
|
||||
#ifdef CONFIG_SYSCTL
|
||||
int proc_nr_inodes(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
inodes_stat.nr_inodes = get_nr_inodes();
|
||||
inodes_stat.nr_unused = get_nr_inodes_unused();
|
||||
|
||||
@@ -539,13 +539,13 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
|
||||
static ssize_t proc_sys_call_handler(struct file *filp, void __user *ubuf,
|
||||
size_t count, loff_t *ppos, int write)
|
||||
{
|
||||
struct inode *inode = file_inode(filp);
|
||||
struct ctl_table_header *head = grab_header(inode);
|
||||
struct ctl_table *table = PROC_I(inode)->sysctl_entry;
|
||||
void *new_buf = NULL;
|
||||
void *kbuf;
|
||||
ssize_t error;
|
||||
|
||||
if (IS_ERR(head))
|
||||
@@ -564,27 +564,38 @@ static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
|
||||
if (!table->proc_handler)
|
||||
goto out;
|
||||
|
||||
error = BPF_CGROUP_RUN_PROG_SYSCTL(head, table, write, buf, &count,
|
||||
ppos, &new_buf);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
/* careful: calling conventions are nasty here */
|
||||
if (new_buf) {
|
||||
mm_segment_t old_fs;
|
||||
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
error = table->proc_handler(table, write, (void __user *)new_buf,
|
||||
&count, ppos);
|
||||
set_fs(old_fs);
|
||||
kfree(new_buf);
|
||||
if (write) {
|
||||
kbuf = memdup_user_nul(ubuf, count);
|
||||
if (IS_ERR(kbuf)) {
|
||||
error = PTR_ERR(kbuf);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
error = table->proc_handler(table, write, buf, &count, ppos);
|
||||
error = -ENOMEM;
|
||||
kbuf = kzalloc(count, GFP_KERNEL);
|
||||
if (!kbuf)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
error = count;
|
||||
error = BPF_CGROUP_RUN_PROG_SYSCTL(head, table, write, &kbuf, &count,
|
||||
ppos);
|
||||
if (error)
|
||||
goto out_free_buf;
|
||||
|
||||
/* careful: calling conventions are nasty here */
|
||||
error = table->proc_handler(table, write, kbuf, &count, ppos);
|
||||
if (error)
|
||||
goto out_free_buf;
|
||||
|
||||
if (!write) {
|
||||
error = -EFAULT;
|
||||
if (copy_to_user(ubuf, kbuf, count))
|
||||
goto out_free_buf;
|
||||
}
|
||||
|
||||
error = count;
|
||||
out_free_buf:
|
||||
kfree(kbuf);
|
||||
out:
|
||||
sysctl_head_finish(head);
|
||||
|
||||
|
||||
@@ -2841,7 +2841,7 @@ const struct quotactl_ops dquot_quotactl_sysfile_ops = {
|
||||
EXPORT_SYMBOL(dquot_quotactl_sysfile_ops);
|
||||
|
||||
static int do_proc_dqstats(struct ctl_table *table, int write,
|
||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||
void *buffer, size_t *lenp, loff_t *ppos)
|
||||
{
|
||||
unsigned int type = (unsigned long *)table->data - dqstats.stat;
|
||||
s64 value = percpu_counter_sum(&dqstats.counter[type]);
|
||||
|
||||
@@ -13,7 +13,7 @@ STATIC int
|
||||
xfs_stats_clear_proc_handler(
|
||||
struct ctl_table *ctl,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
void *buffer,
|
||||
size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
@@ -33,7 +33,7 @@ STATIC int
|
||||
xfs_panic_mask_proc_handler(
|
||||
struct ctl_table *ctl,
|
||||
int write,
|
||||
void __user *buffer,
|
||||
void *buffer,
|
||||
size_t *lenp,
|
||||
loff_t *ppos)
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user