All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <keescook@chromium.org>
To: Ondrej Mosnacek <omosnace@redhat.com>
Cc: Luis Chamberlain <mcgrof@kernel.org>,
	Iurii Zaikin <yzaikin@google.com>,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jirislaby@kernel.org>,
	linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org,
	linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] sysctl: fix proc_dobool() usability
Date: Tue, 21 Feb 2023 09:34:49 -0800	[thread overview]
Message-ID: <63f500ba.170a0220.c76fc.1642@mx.google.com> (raw)
In-Reply-To: <20230210145823.756906-1-omosnace@redhat.com>

On Fri, Feb 10, 2023 at 03:58:23PM +0100, Ondrej Mosnacek wrote:
> 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: 83efeeeb3d04 ("tty: Allow TIOCSTI to be disabled")
> Fixes: a2071573d634 ("sysctl: introduce new proc handler proc_dobool")
> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>

Ah nice, thanks for tracking this down.

Acked-by: Kees Cook <keescook@chromium.org>

I've long wanted to replace all the open-coded sysctl initializers with
a helper macro so it's hard to make mistakes. e.g.

#define _SYSCTL_HANDLER(var)					\
		_Generic((var),					\
			default:	proc_dointvec_minmax,	\
			unsigned int:	proc_douintvec_minmax,	\
			unsigned long:	proc_doulongvec_minmax,	\
			char:		proc_dou8vec_minmax,	\
			bool:		proc_dobool,		\
			char *:		proc_dostring)

#define _SYSCTL_MINVAL(var)				\
		_Generic((var),				\
			default:	0,		\
			int:		INT_MIN,	\
			unsigned int:	UINT_MIN,	\
			unsigned long:	ULONG_MIN,	\
			char:		U8_MIN,		\
			bool:		0)

#define _SYSCTL_MAXVAL(var)				\
		_Generic((var),				\
			default:	0,		\
			int:		INT_MAX,	\
			unsigned int:	UINT_MAX,	\
			unsigned long:	ULONG_MAX,	\
			char:		U8_MAX,		\
			bool:		1)

#define _SYSCTL_VAR(_name, _var, _mode, _handler, _len, _min, _max)	\
	{								\
		.procname	= _name,				\
		.data		= &(_var),				\
		.maxlen		= _len,					\
		.mode		= _mode,				\
		.proc_handler	= _handler,				\
		.minlen		= _min,					\
		.maxlen		= _min,					\
	}

/* single value */
#define SYSCTL_VAL(var)							\
	_SYSCTL_VAR(#var, var, 0644, _SYSCTL_HANDLER(var), sizeof(var),	\
		    _SYSCTL_MINVAL(var), _SYSCTL_MAXVAL(var))

/* single value with min/max */
#define SYSCTL_VAL_MINMAX(_var, _min, _max)				\
	_SYSCTL_VAR(#var, var, 0644, _SYSCTL_HANDLER(var), sizeof(var),	\
		    _min, _max)

/* Strings... */
#define SYSCTL_STR(_var, _len)						\
	_SYSCTL_VAR(#var, var, 0644, _SYSCTL_HANDLER(var), _len, 0, 0)

/* Arrays... */
#define SYSCTL_ARRAY(_var)						\
	_SYSCTL_VAR(#var, var, 0644, _SYSCTL_HANDLER(var),		\
		    ARRAY_SIZE(_var), _SYSCTL_MINVAL(var),		\
		    _SYSCTL_MAXVAL(var)

Totally untested. I think this would cover the vast majority of sysctl
initializers.

-- 
Kees Cook

  parent reply	other threads:[~2023-02-21 17:35 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-10 14:58 [PATCH] sysctl: fix proc_dobool() usability Ondrej Mosnacek
2023-02-20 12:52 ` Ondrej Mosnacek
2023-02-21 17:34 ` Kees Cook [this message]
2023-02-21 21:36   ` Luis Chamberlain
2023-02-22  7:52     ` Ondrej Mosnacek
2023-03-05  2:18 ` Request to backport "sysctl: fix proc_dobool() usability" to stable kernels Thomas Weißschuh
2023-03-05  2:51   ` Storm Dragon
2023-03-05  3:06     ` Thomas Weißschuh
2023-03-06 17:47       ` Storm Dragon

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=63f500ba.170a0220.c76fc.1642@mx.google.com \
    --to=keescook@chromium.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=mcgrof@kernel.org \
    --cc=omosnace@redhat.com \
    --cc=yzaikin@google.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.