Skip to content

Commit

Permalink
proc/sysctl: add shared variables for range check
Browse files Browse the repository at this point in the history
In the sysctl code the proc_dointvec_minmax() function is often used to
validate the user supplied value between an allowed range.  This function
uses the extra1 and extra2 members from struct ctl_table as minimum and
maximum allowed value.

On sysctl handler declaration, in every source file there are some
readonly variables containing just an integer which address is assigned to
the extra1 and extra2 members, so the sysctl range is enforced.

The special values 0, 1 and INT_MAX are very often used as range boundary,
leading duplication of variables like zero=0, one=1, int_max=INT_MAX in
different source files:

    $ git grep -E '\.extra[12].*&(zero|one|int_max)' |wc -l
    248

Add a const int array containing the most commonly used values, some
macros to refer more easily to the correct array member, and use them
instead of creating a local one for every object file.

This is the bloat-o-meter output comparing the old and new binary compiled
with the default Fedora config:

    # scripts/bloat-o-meter -d vmlinux.o.old vmlinux.o
    add/remove: 2/2 grow/shrink: 0/2 up/down: 24/-188 (-164)
    Data                                         old     new   delta
    sysctl_vals                                    -      12     +12
    __kstrtab_sysctl_vals                          -      12     +12
    max                                           14      10      -4
    int_max                                       16       -     -16
    one                                           68       -     -68
    zero                                         128      28    -100
    Total: Before=20583249, After=20583085, chg -0.00%

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Matteo Croce <[email protected]>
Acked-by: Kees Cook <[email protected]>
Reviewed-by: Aaron Tomlin <[email protected]>
Cc: Matthew Wilcox <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Stephen Rothwell <[email protected]>
  • Loading branch information
teknoraver authored and sfrothwell committed May 31, 2019
1 parent 723b313 commit d91bff3
Show file tree
Hide file tree
Showing 34 changed files with 266 additions and 322 deletions.
15 changes: 5 additions & 10 deletions arch/s390/appldata/appldata_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,13 @@ appldata_timer_handler(struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int timer_active = appldata_timer_active;
int zero = 0;
int one = 1;
int rc;
struct ctl_table ctl_entry = {
.procname = ctl->procname,
.data = &timer_active,
.maxlen = sizeof(int),
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
};

rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
Expand All @@ -255,13 +253,12 @@ appldata_interval_handler(struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int interval = appldata_interval;
int one = 1;
int rc;
struct ctl_table ctl_entry = {
.procname = ctl->procname,
.data = &interval,
.maxlen = sizeof(int),
.extra1 = &one,
.extra1 = SYSCTL_ONE,
};

rc = proc_dointvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
Expand Down Expand Up @@ -289,13 +286,11 @@ appldata_generic_handler(struct ctl_table *ctl, int write,
struct list_head *lh;
int rc, found;
int active;
int zero = 0;
int one = 1;
struct ctl_table ctl_entry = {
.data = &active,
.maxlen = sizeof(int),
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
};

found = 0;
Expand Down
6 changes: 2 additions & 4 deletions arch/s390/kernel/topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,15 +587,13 @@ static int topology_ctl_handler(struct ctl_table *ctl, int write,
{
int enabled = topology_is_enabled();
int new_mode;
int zero = 0;
int one = 1;
int rc;
struct ctl_table ctl_entry = {
.procname = ctl->procname,
.data = &enabled,
.maxlen = sizeof(int),
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
};

rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
Expand Down
7 changes: 2 additions & 5 deletions arch/x86/entry/vdso/vdso32-setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,15 @@ subsys_initcall(sysenter_setup);
/* Register vsyscall32 into the ABI table */
#include <linux/sysctl.h>

static const int zero;
static const int one = 1;

static struct ctl_table abi_table2[] = {
{
.procname = "vsyscall32",
.data = &vdso32_enabled,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = (int *)&zero,
.extra2 = (int *)&one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{}
};
Expand Down
6 changes: 2 additions & 4 deletions arch/x86/kernel/itmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,17 +69,15 @@ static int sched_itmt_update_handler(struct ctl_table *table, int write,
return ret;
}

static unsigned int zero;
static unsigned int one = 1;
static struct ctl_table itmt_kern_table[] = {
{
.procname = "sched_itmt_enabled",
.data = &sysctl_sched_itmt_enabled,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = sched_itmt_update_handler,
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{}
};
Expand Down
11 changes: 4 additions & 7 deletions drivers/base/firmware_loader/fallback_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
* firmware fallback configuration table
*/

static unsigned int zero;
static unsigned int one = 1;

struct firmware_fallback_config fw_fallback_config = {
.force_sysfs_fallback = IS_ENABLED(CONFIG_FW_LOADER_USER_HELPER_FALLBACK),
.loading_timeout = 60,
Expand All @@ -33,17 +30,17 @@ struct ctl_table firmware_config_table[] = {
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_douintvec_minmax,
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{
.procname = "ignore_sysfs_fallback",
.data = &fw_fallback_config.ignore_sysfs_fallback,
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_douintvec_minmax,
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{ }
};
Expand Down
8 changes: 3 additions & 5 deletions drivers/gpu/drm/i915/i915_perf.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,6 @@
#define POLL_PERIOD (NSEC_PER_SEC / POLL_FREQUENCY)

/* for sysctl proc_dointvec_minmax of dev.i915.perf_stream_paranoid */
static int zero;
static int one = 1;
static u32 i915_perf_stream_paranoid = true;

/* The maximum exponent the hardware accepts is 63 (essentially it selects one
Expand Down Expand Up @@ -3343,16 +3341,16 @@ static struct ctl_table oa_table[] = {
.maxlen = sizeof(i915_perf_stream_paranoid),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{
.procname = "oa_max_sample_rate",
.data = &i915_oa_max_sample_rate,
.maxlen = sizeof(i915_oa_max_sample_rate),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra1 = SYSCTL_ZERO,
.extra2 = &oa_sample_rate_hard_limit,
},
{}
Expand Down
6 changes: 2 additions & 4 deletions drivers/hv/vmbus_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1219,8 +1219,6 @@ static struct kmsg_dumper hv_kmsg_dumper = {
};

static struct ctl_table_header *hv_ctl_table_hdr;
static int zero;
static int one = 1;

/*
* sysctl option to allow the user to control whether kmsg data should be
Expand All @@ -1233,8 +1231,8 @@ static struct ctl_table hv_ctl_table[] = {
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &one
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE
},
{}
};
Expand Down
7 changes: 2 additions & 5 deletions drivers/s390/char/sclp_async.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,15 @@ static struct notifier_block call_home_panic_nb = {
.priority = INT_MAX,
};

static int zero;
static int one = 1;

static struct ctl_table callhome_table[] = {
{
.procname = "callhome",
.data = &callhome_enabled,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{}
};
Expand Down
6 changes: 2 additions & 4 deletions drivers/tty/tty_ldisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -855,17 +855,15 @@ void tty_ldisc_deinit(struct tty_struct *tty)
tty->ldisc = NULL;
}

static int zero;
static int one = 1;
static struct ctl_table tty_table[] = {
{
.procname = "ldisc_autoload",
.data = &tty_ldisc_autoload,
.maxlen = sizeof(tty_ldisc_autoload),
.mode = 0644,
.proc_handler = proc_dointvec,
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{ }
};
Expand Down
7 changes: 2 additions & 5 deletions drivers/xen/balloon.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,15 @@ static int xen_hotplug_unpopulated;

#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG

static int zero;
static int one = 1;

static struct ctl_table balloon_table[] = {
{
.procname = "hotplug_unpopulated",
.data = &xen_hotplug_unpopulated,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra2 = &one,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
{ }
};
Expand Down
3 changes: 1 addition & 2 deletions fs/eventpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,6 @@ static LIST_HEAD(tfile_check_list);

#include <linux/sysctl.h>

static long zero;
static long long_max = LONG_MAX;

struct ctl_table epoll_table[] = {
Expand All @@ -306,7 +305,7 @@ struct ctl_table epoll_table[] = {
.maxlen = sizeof(max_user_watches),
.mode = 0644,
.proc_handler = proc_doulongvec_minmax,
.extra1 = &zero,
.extra1 = SYSCTL_ZERO,
.extra2 = &long_max,
},
{ }
Expand Down
8 changes: 3 additions & 5 deletions fs/notify/inotify/inotify_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,32 +45,30 @@ struct kmem_cache *inotify_inode_mark_cachep __read_mostly;

#include <linux/sysctl.h>

static int zero;

struct ctl_table inotify_table[] = {
{
.procname = "max_user_instances",
.data = &init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES],
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra1 = SYSCTL_ZERO,
},
{
.procname = "max_user_watches",
.data = &init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES],
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero,
.extra1 = SYSCTL_ZERO,
},
{
.procname = "max_queued_events",
.data = &inotify_max_queued_events,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = &zero
.extra1 = SYSCTL_ZERO
},
{ }
};
Expand Down
4 changes: 4 additions & 0 deletions fs/proc/proc_sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ static const struct inode_operations proc_sys_inode_operations;
static const struct file_operations proc_sys_dir_file_operations;
static const struct inode_operations proc_sys_dir_operations;

/* shared constants to be used in various sysctls */
const int sysctl_vals[] = { 0, 1, INT_MAX };
EXPORT_SYMBOL(sysctl_vals);

/* Support for permanently empty directories */

struct ctl_table sysctl_mount_point[] = {
Expand Down
7 changes: 7 additions & 0 deletions include/linux/sysctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ struct ctl_table_root;
struct ctl_table_header;
struct ctl_dir;

/* Keep the same order as in fs/proc/proc_sysctl.c */
#define SYSCTL_ZERO ((void *)&sysctl_vals[0])
#define SYSCTL_ONE ((void *)&sysctl_vals[1])
#define SYSCTL_INT_MAX ((void *)&sysctl_vals[2])

extern const int sysctl_vals[];

typedef int proc_handler (struct ctl_table *ctl, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);

Expand Down
Loading

0 comments on commit d91bff3

Please sign in to comment.