All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vegard Nossum <vegard.nossum-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
To: "Michael Kerrisk (man-pages)"
	<mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>,
	Andrew Morton
	<akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org>
Cc: Willy Tarreau <w@1wt.eu>,
	socketpair-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
	Tetsuo Handa
	<penguin-kernel-JPay3/Yim36HaxMnTkn67Xf5DAMn2ifp@public.gmane.org>,
	Jens Axboe <axboe-b10kYP2dOMg@public.gmane.org>,
	Al Viro <viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org>,
	linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
Subject: Re: [PATCH 4/8] pipe: fix limit checking in pipe_set_size()
Date: Fri, 19 Aug 2016 10:30:47 +0200	[thread overview]
Message-ID: <57B6C3B7.2000903@oracle.com> (raw)
In-Reply-To: <7f0732a9-6172-e92d-7c5b-473b769fe37e-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On 08/19/2016 07:25 AM, Michael Kerrisk (man-pages) wrote:
> The limit checking in pipe_set_size() (used by fcntl(F_SETPIPE_SZ))
> has the following problems:
[...]
> @@ -1030,6 +1030,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
>   {
>   	struct pipe_buffer *bufs;
>   	unsigned int size, nr_pages;
> +	long ret = 0;
>
>   	size = round_pipe_size(arg);
>   	nr_pages = size >> PAGE_SHIFT;
> @@ -1037,13 +1038,26 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
>   	if (!nr_pages)
>   		return -EINVAL;
>
> -	if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size)
> -		return -EPERM;
> +	account_pipe_buffers(pipe->user, pipe->buffers, nr_pages);
>
> -	if ((too_many_pipe_buffers_hard(pipe->user) ||
> -			too_many_pipe_buffers_soft(pipe->user)) &&
> -			!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
> -		return -EPERM;
> +	/*
> +	 * If trying to increase the pipe capacity, check that an
> +	 * unprivileged user is not trying to exceed various limits.
> +	 * (Decreasing the pipe capacity is always permitted, even
> +	 * if the user is currently over a limit.)
> +	 */
> +	if (nr_pages > pipe->buffers) {
> +		if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
> +			ret = -EPERM;
> +			goto out_revert_acct;
> +		} else if ((too_many_pipe_buffers_hard(pipe->user) ||
> +				too_many_pipe_buffers_soft(pipe->user)) &&
> +				!capable(CAP_SYS_RESOURCE) &&
> +				!capable(CAP_SYS_ADMIN)) {
> +			ret = -EPERM;
> +			goto out_revert_acct;
> +		}
> +	}

I'm slightly worried about not checking arg/nr_pages before we pass it
on to account_pipe_buffers().

The potential problem happens if the user passes a very large number
which will overflow pipe->user->pipe_bufs.

On 32-bit, sizeof(int) == sizeof(long), so if they pass arg = INT_MAX
then round_pipe_size() returns INT_MAX. Although it's true that the
accounting is done in terms of pages and not bytes, so you'd need on the
order of (1 << 13) = 8192 processes hitting the limit at the same time
in order to make it overflow, which seems a bit unlikely.

(See https://lkml.org/lkml/2016/8/12/215 for another discussion on the
limit checking)

Is there any reason why we couldn't do the (size > pipe_max_size) check
before calling account_pipe_buffers()?


Vegard

WARNING: multiple messages have this Message-ID (diff)
From: Vegard Nossum <vegard.nossum@oracle.com>
To: "Michael Kerrisk (man-pages)" <mtk.manpages@gmail.com>,
	Andrew Morton <akpm@linux-foundation.org>
Cc: Willy Tarreau <w@1wt.eu>,
	socketpair@gmail.com,
	Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
	Jens Axboe <axboe@fb.com>, Al Viro <viro@zeniv.linux.org.uk>,
	linux-api@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 4/8] pipe: fix limit checking in pipe_set_size()
Date: Fri, 19 Aug 2016 10:30:47 +0200	[thread overview]
Message-ID: <57B6C3B7.2000903@oracle.com> (raw)
In-Reply-To: <7f0732a9-6172-e92d-7c5b-473b769fe37e@gmail.com>

On 08/19/2016 07:25 AM, Michael Kerrisk (man-pages) wrote:
> The limit checking in pipe_set_size() (used by fcntl(F_SETPIPE_SZ))
> has the following problems:
[...]
> @@ -1030,6 +1030,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
>   {
>   	struct pipe_buffer *bufs;
>   	unsigned int size, nr_pages;
> +	long ret = 0;
>
>   	size = round_pipe_size(arg);
>   	nr_pages = size >> PAGE_SHIFT;
> @@ -1037,13 +1038,26 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
>   	if (!nr_pages)
>   		return -EINVAL;
>
> -	if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size)
> -		return -EPERM;
> +	account_pipe_buffers(pipe->user, pipe->buffers, nr_pages);
>
> -	if ((too_many_pipe_buffers_hard(pipe->user) ||
> -			too_many_pipe_buffers_soft(pipe->user)) &&
> -			!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN))
> -		return -EPERM;
> +	/*
> +	 * If trying to increase the pipe capacity, check that an
> +	 * unprivileged user is not trying to exceed various limits.
> +	 * (Decreasing the pipe capacity is always permitted, even
> +	 * if the user is currently over a limit.)
> +	 */
> +	if (nr_pages > pipe->buffers) {
> +		if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
> +			ret = -EPERM;
> +			goto out_revert_acct;
> +		} else if ((too_many_pipe_buffers_hard(pipe->user) ||
> +				too_many_pipe_buffers_soft(pipe->user)) &&
> +				!capable(CAP_SYS_RESOURCE) &&
> +				!capable(CAP_SYS_ADMIN)) {
> +			ret = -EPERM;
> +			goto out_revert_acct;
> +		}
> +	}

I'm slightly worried about not checking arg/nr_pages before we pass it
on to account_pipe_buffers().

The potential problem happens if the user passes a very large number
which will overflow pipe->user->pipe_bufs.

On 32-bit, sizeof(int) == sizeof(long), so if they pass arg = INT_MAX
then round_pipe_size() returns INT_MAX. Although it's true that the
accounting is done in terms of pages and not bytes, so you'd need on the
order of (1 << 13) = 8192 processes hitting the limit at the same time
in order to make it overflow, which seems a bit unlikely.

(See https://lkml.org/lkml/2016/8/12/215 for another discussion on the
limit checking)

Is there any reason why we couldn't do the (size > pipe_max_size) check
before calling account_pipe_buffers()?


Vegard

  parent reply	other threads:[~2016-08-19  8:30 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <67ce15aa-cf43-0c89-d079-2d966177c56d@gmail.com>
2016-08-19  5:25 ` [PATCH 1/8] pipe: relocate round_pipe_size() above pipe_set_size() Michael Kerrisk (man-pages)
     [not found] ` <67ce15aa-cf43-0c89-d079-2d966177c56d-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-08-19  5:25   ` [PATCH 2/8] pipe: move limit checking logic into pipe_set_size() Michael Kerrisk (man-pages)
2016-08-19  5:25     ` Michael Kerrisk (man-pages)
2016-08-19  5:25   ` [PATCH 6/8] pipe: fix limit checking in alloc_pipe_info() Michael Kerrisk (man-pages)
2016-08-19  5:25     ` Michael Kerrisk (man-pages)
2016-08-19  5:25 ` [PATCH 3/8] pipe: refactor argument for account_pipe_buffers() Michael Kerrisk (man-pages)
2016-08-19  5:25 ` [PATCH 4/8] pipe: fix limit checking in pipe_set_size() Michael Kerrisk (man-pages)
     [not found]   ` <7f0732a9-6172-e92d-7c5b-473b769fe37e-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-08-19  5:48     ` Willy Tarreau
2016-08-19  5:48       ` Willy Tarreau
     [not found]       ` <20160819054818.GH17944-K+wRfnb2/UA@public.gmane.org>
2016-08-19 20:51         ` Michael Kerrisk (man-pages)
2016-08-19 20:51           ` Michael Kerrisk (man-pages)
2016-08-21 21:15         ` Michael Kerrisk (man-pages)
2016-08-21 21:15           ` Michael Kerrisk (man-pages)
2016-08-21 21:35           ` Willy Tarreau
     [not found]             ` <20160821213541.GA3864-K+wRfnb2/UA@public.gmane.org>
2016-08-22 19:37               ` Michael Kerrisk (man-pages)
2016-08-22 19:37                 ` Michael Kerrisk (man-pages)
2016-08-19  8:30     ` Vegard Nossum [this message]
2016-08-19  8:30       ` Vegard Nossum
     [not found]       ` <57B6C3B7.2000903-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
2016-08-19 20:56         ` Michael Kerrisk (man-pages)
2016-08-19 20:56           ` Michael Kerrisk (man-pages)
     [not found]           ` <a451bb84-4a38-b00c-5bbb-dbaf914b8788-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-08-19 23:17             ` Michael Kerrisk (man-pages)
2016-08-19 23:17               ` Michael Kerrisk (man-pages)
     [not found]               ` <ea75f57d-9bb8-33b5-3b63-8f99f4981561-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-08-21 10:33                 ` Vegard Nossum
2016-08-21 10:33                   ` Vegard Nossum
     [not found]                   ` <f99fff13-aacf-8673-8553-366f6c952654-QHcLZuEGTsvQT0dZR+AlfA@public.gmane.org>
2016-08-21 21:14                     ` Michael Kerrisk (man-pages)
2016-08-21 21:14                       ` Michael Kerrisk (man-pages)
2016-08-19  5:25 ` [PATCH 5/8] pipe: simplify logic in alloc_pipe_info() Michael Kerrisk (man-pages)
2016-08-19  5:25 ` [PATCH 7/8] pipe: make account_pipe_buffers() return a value, and use it Michael Kerrisk (man-pages)
     [not found]   ` <676aa52b-c4fc-3bf1-8051-39deca8bf0ab-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2016-08-19  9:36     ` Vegard Nossum
2016-08-19  9:36       ` Vegard Nossum
2016-08-19 20:51       ` Michael Kerrisk (man-pages)
2016-08-19  5:26 ` [PATCH 8/8] pipe: cap initial pipe capacity according to pipe-max-size limit Michael Kerrisk (man-pages)

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=57B6C3B7.2000903@oracle.com \
    --to=vegard.nossum-qhclzuegtsvqt0dzr+alfa@public.gmane.org \
    --cc=akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b@public.gmane.org \
    --cc=axboe-b10kYP2dOMg@public.gmane.org \
    --cc=linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=penguin-kernel-JPay3/Yim36HaxMnTkn67Xf5DAMn2ifp@public.gmane.org \
    --cc=socketpair-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
    --cc=viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn@public.gmane.org \
    --cc=w@1wt.eu \
    /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.