• Ondrej Mosnacek's avatar
    sysctl: fix proc_dobool() usability · f1aa2eb5
    Ondrej Mosnacek authored
    Currently proc_dobool expects a (bool *) in table->data, but sizeof(int)
    in table->maxsize, because it uses do_proc_dointvec() directly.
    
    This is unsafe for at least two reasons:
    1. A sysctl table definition may use { .data = &variable, .maxsize =
       sizeof(variable) }, not realizing that this makes the sysctl unusable
       (see the Fixes: tag) and that they need to use the completely
       counterintuitive sizeof(int) instead.
    2. proc_dobool() will currently try to parse an array of values if given
       .maxsize >= 2*sizeof(int), but will try to write values of type bool
       by offsets of sizeof(int), so it will not work correctly with neither
       an (int *) nor a (bool *). There is no .maxsize validation to prevent
       this.
    
    Fix this by:
    1. Constraining proc_dobool() to allow only one value and .maxsize ==
       sizeof(bool).
    2. Wrapping the original struct ctl_table in a temporary one with .data
       pointing to a local int variable and .maxsize set to sizeof(int) and
       passing this one to proc_dointvec(), converting the value to/from
       bool as needed (using proc_dou8vec_minmax() as an example).
    3. Extending sysctl_check_table() to enforce proc_dobool() expectations.
    4. Fixing the proc_dobool() docstring (it was just copy-pasted from
       proc_douintvec, apparently...).
    5. Converting all existing proc_dobool() users to set .maxsize to
       sizeof(bool) instead of sizeof(int).
    
    Fixes: 83efeeeb ("tty: Allow TIOCSTI to be disabled")
    Fixes: a2071573 ("sysctl: introduce new proc handler proc_dobool")
    Signed-off-by: default avatarOndrej Mosnacek <omosnace@redhat.com>
    Acked-by: default avatarKees Cook <keescook@chromium.org>
    Signed-off-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
    f1aa2eb5
sysctl.c 59.4 KB