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%

[[email protected]: tipc: remove two unused variables]
  Link: http://lkml.kernel.org/r/[email protected]
[[email protected]: fix net/ipv6/sysctl_net_ipv6.c]
[[email protected]: proc/sysctl: make firmware loader table conditional]
  Link: http://lkml.kernel.org/r/[email protected]
[[email protected]: fix fs/eventpoll.c]
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Matteo Croce <[email protected]>
Signed-off-by: Arnd Bergmann <[email protected]>
Acked-by: Kees Cook <[email protected]>
Reviewed-by: Aaron Tomlin <[email protected]>
Cc: Matthew Wilcox <[email protected]>
Cc: Stephen Rothwell <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
teknoraver authored and torvalds committed Jul 19, 2019
1 parent 3710969 commit eec4844
Show file tree
Hide file tree
Showing 33 changed files with 270 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 @@ -65,17 +65,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
13 changes: 6 additions & 7 deletions drivers/base/firmware_loader/fallback_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,34 @@
* 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,
.old_timeout = 60,
};
EXPORT_SYMBOL_GPL(fw_fallback_config);

#ifdef CONFIG_SYSCTL
struct ctl_table firmware_config_table[] = {
{
.procname = "force_sysfs_fallback",
.data = &fw_fallback_config.force_sysfs_fallback,
.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,
},
{ }
};
EXPORT_SYMBOL_GPL(firmware_config_table);
#endif
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 @@ -274,8 +274,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 @@ -3366,16 +3364,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 @@ -1197,8 +1197,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 @@ -1211,8 +1209,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
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
4 changes: 2 additions & 2 deletions fs/eventpoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ static LIST_HEAD(tfile_check_list);

#include <linux/sysctl.h>

static long zero;
static long long_zero;
static long long_max = LONG_MAX;

struct ctl_table epoll_table[] = {
Expand All @@ -301,7 +301,7 @@ struct ctl_table epoll_table[] = {
.maxlen = sizeof(max_user_watches),
.mode = 0644,
.proc_handler = proc_doulongvec_minmax,
.extra1 = &zero,
.extra1 = &long_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 eec4844

Please sign in to comment.