Skip to content

Commit

Permalink
sysctl: pass kernel pointers to ->proc_handler
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and Al Viro committed Apr 27, 2020
1 parent f461d2d commit 3292739
Show file tree
Hide file tree
Showing 88 changed files with 458 additions and 653 deletions.
2 changes: 1 addition & 1 deletion arch/arm64/kernel/armv8_deprecated.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions arch/arm64/kernel/fpsimd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 5 additions & 8 deletions arch/mips/lasat/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
Expand Down
11 changes: 5 additions & 6 deletions arch/s390/appldata/appldata_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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[] = {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 5 additions & 7 deletions arch/s390/mm/cmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -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();
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kernel/itmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/cdrom/cdrom.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion drivers/char/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 1 addition & 2 deletions drivers/macintosh/mac_hid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
39 changes: 18 additions & 21 deletions drivers/parport/procfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand All @@ -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];
Expand Down Expand Up @@ -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 }
Expand Down
2 changes: 1 addition & 1 deletion fs/dcache.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
2 changes: 1 addition & 1 deletion fs/drop_caches.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
4 changes: 2 additions & 2 deletions fs/file_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
3 changes: 1 addition & 2 deletions fs/fscache/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion fs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
Loading

0 comments on commit 3292739

Please sign in to comment.