public inbox for linux-nfs@vger.kernel.org
 help / color / mirror / Atom feed
From: "J. Bruce Fields" <bfields@fieldses.org>
To: Chuck Lever <chuck.lever@oracle.com>
Cc: linux-nfs@vger.kernel.org
Subject: Re: [PATCH 09/19] NFSD: Prevent a buffer overflow in svc_xprt_names()
Date: Mon, 27 Apr 2009 19:56:44 -0400	[thread overview]
Message-ID: <20090427235644.GE5108@fieldses.org> (raw)
In-Reply-To: <20090423233225.17283.10176.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>

On Thu, Apr 23, 2009 at 07:32:25PM -0400, Chuck Lever wrote:
> The svc_xprt_names() function can overflow its buffer if it's so near
> the end of the passed in buffer that the "name too long" string still
> doesn't fit.  Of course, it could never tell if it was near the end
> of the passed in buffer, since its only caller passes in zero as the
> buffer length.
> 
> Let's make this API a little safer.
> 
> Change svc_xprt_names() so it *always* checks for a buffer overflow,
> and change its only caller to pass in the correct buffer length.
> 
> If svc_xprt_names() does overflow its buffer, it now fails with an
> ENAMETOOLONG errno, instead of trying to write a message at the end
> of the buffer.  I don't like this much, but I can't figure out a clean
> way that's always safe to return some of the names, *and* an
> indication that the buffer was not long enough.
> 
> The displayed error when doing a 'cat /proc/fs/nfsd/portlist' is
> "File name too long".

Also worth noting that the buffer in question is nearly a page, which
makes this a bit academic for now.  (Not an objection to the patch, just
something to note.)

--b.

> 
> Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
> ---
> 
>  fs/nfsd/nfsctl.c                |    2 +
>  include/linux/sunrpc/svc_xprt.h |    2 +
>  net/sunrpc/svc_xprt.c           |   56 +++++++++++++++++++++++++++------------
>  3 files changed, 41 insertions(+), 19 deletions(-)
> 
> diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
> index e051847..6a1cd90 100644
> --- a/fs/nfsd/nfsctl.c
> +++ b/fs/nfsd/nfsctl.c
> @@ -918,7 +918,7 @@ static ssize_t __write_ports_names(char *buf)
>  {
>  	if (nfsd_serv == NULL)
>  		return 0;
> -	return svc_xprt_names(nfsd_serv, buf, 0);
> +	return svc_xprt_names(nfsd_serv, buf, SIMPLE_TRANSACTION_LIMIT);
>  }
>  
>  /*
> diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
> index d790c52..2223ae0 100644
> --- a/include/linux/sunrpc/svc_xprt.h
> +++ b/include/linux/sunrpc/svc_xprt.h
> @@ -83,7 +83,7 @@ int	svc_port_is_privileged(struct sockaddr *sin);
>  int	svc_print_xprts(char *buf, int maxlen);
>  struct	svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
>  			const sa_family_t af, const unsigned short port);
> -int	svc_xprt_names(struct svc_serv *serv, char *buf, int buflen);
> +int	svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen);
>  
>  static inline void svc_xprt_get(struct svc_xprt *xprt)
>  {
> diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
> index c200d92..96eb873 100644
> --- a/net/sunrpc/svc_xprt.c
> +++ b/net/sunrpc/svc_xprt.c
> @@ -1097,36 +1097,58 @@ struct svc_xprt *svc_find_xprt(struct svc_serv *serv, const char *xcl_name,
>  }
>  EXPORT_SYMBOL_GPL(svc_find_xprt);
>  
> -/*
> - * Format a buffer with a list of the active transports. A zero for
> - * the buflen parameter disables target buffer overflow checking.
> +static int svc_one_xprt_name(const struct svc_xprt *xprt,
> +			     char *pos, int remaining)
> +{
> +	int len;
> +
> +	len = snprintf(pos, remaining, "%s %u\n",
> +			xprt->xpt_class->xcl_name,
> +			svc_xprt_local_port(xprt));
> +	if (len >= remaining)
> +		return -ENAMETOOLONG;
> +	return len;
> +}
> +
> +/**
> + * svc_xprt_names - format a buffer with a list of transport names
> + * @serv: pointer to an RPC service
> + * @buf: pointer to a buffer to be filled in
> + * @buflen: length of buffer to be filled in
> + *
> + * Fills in @buf with a string containing a list of transport names,
> + * each name terminated with '\n'.
> + *
> + * Returns positive length of the filled-in string on success; otherwise
> + * a negative errno value is returned if an error occurs.
>   */
> -int svc_xprt_names(struct svc_serv *serv, char *buf, int buflen)
> +int svc_xprt_names(struct svc_serv *serv, char *buf, const int buflen)
>  {
>  	struct svc_xprt *xprt;
> -	char xprt_str[64];
> -	int totlen = 0;
> -	int len;
> +	int len, totlen;
> +	char *pos;
>  
>  	/* Sanity check args */
>  	if (!serv)
>  		return 0;
>  
>  	spin_lock_bh(&serv->sv_lock);
> +
> +	pos = buf;
> +	totlen = 0;
>  	list_for_each_entry(xprt, &serv->sv_permsocks, xpt_list) {
> -		len = snprintf(xprt_str, sizeof(xprt_str),
> -			       "%s %d\n", xprt->xpt_class->xcl_name,
> -			       svc_xprt_local_port(xprt));
> -		/* If the string was truncated, replace with error string */
> -		if (len >= sizeof(xprt_str))
> -			strcpy(xprt_str, "name-too-long\n");
> -		/* Don't overflow buffer */
> -		len = strlen(xprt_str);
> -		if (buflen && (len + totlen >= buflen))
> +		len = svc_one_xprt_name(xprt, pos, buflen - totlen);
> +		if (len < 0) {
> +			*buf = '\0';
> +			totlen = len;
> +		}
> +		if (len <= 0)
>  			break;
> -		strcpy(buf+totlen, xprt_str);
> +
> +		pos += len;
>  		totlen += len;
>  	}
> +
>  	spin_unlock_bh(&serv->sv_lock);
>  	return totlen;
>  }
> 

  parent reply	other threads:[~2009-04-27 23:56 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-23 23:31 [PATCH 00/19] Proposed server-side patches for 2.6.31 Chuck Lever
     [not found] ` <20090423231550.17283.24432.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-04-23 23:31   ` [PATCH 01/19] SUNRPC: Fix error return value of svc_addr_len() Chuck Lever
     [not found]     ` <20090423233124.17283.40252.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-04-25 22:17       ` J. Bruce Fields
2009-04-27 16:49         ` Chuck Lever
2009-04-27 23:51           ` J. Bruce Fields
2009-04-28 15:28             ` Chuck Lever
2009-04-28 15:31               ` J. Bruce Fields
2009-04-23 23:31   ` [PATCH 02/19] NFSD: Refactor transport removal out of __write_ports() Chuck Lever
2009-04-23 23:31   ` [PATCH 03/19] NFSD: Refactor transport addition " Chuck Lever
2009-04-23 23:31   ` [PATCH 04/19] NFSD: Refactor portlist socket closing into a helper Chuck Lever
2009-04-23 23:31   ` [PATCH 05/19] NFSD: Refactor socket creation out of __write_ports() Chuck Lever
     [not found]     ` <20090423233155.17283.37345.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-04-25 22:40       ` J. Bruce Fields
2009-04-23 23:32   ` [PATCH 06/19] NFSD: Note an additional requirement when passing TCP sockets to portlist Chuck Lever
2009-04-23 23:32   ` [PATCH 07/19] NFSD: Finish refactoring __write_ports() Chuck Lever
2009-04-23 23:32   ` [PATCH 08/19] NFSD: move lockd_up() before svc_addsock() Chuck Lever
2009-04-23 23:32   ` [PATCH 09/19] NFSD: Prevent a buffer overflow in svc_xprt_names() Chuck Lever
     [not found]     ` <20090423233225.17283.10176.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-04-27 23:56       ` J. Bruce Fields [this message]
2009-04-23 23:32   ` [PATCH 10/19] SUNRPC: pass buffer size to svc_addsock() Chuck Lever
2009-04-23 23:32   ` [PATCH 11/19] SUNRPC: pass buffer size to svc_sock_names() Chuck Lever
2009-04-23 23:32   ` [PATCH 12/19] SUNRPC: Switch one_sock_name() to use snprintf() Chuck Lever
2009-04-23 23:32   ` [PATCH 13/19] SUNRPC: Support PF_INET6 in one_sock_name() Chuck Lever
2009-04-23 23:33   ` [PATCH 14/19] SUNRPC: Clean up one_sock_name() Chuck Lever
2009-04-23 23:33   ` [PATCH 15/19] NFSD: Stricter buffer size checking in write_recoverydir() Chuck Lever
2009-04-23 23:33   ` [PATCH 16/19] NFSD: Stricter buffer size checking in write_versions() Chuck Lever
2009-04-23 23:33   ` [PATCH 17/19] NFSD: Stricter buffer size checking in fs/nfsd/nfsctl.c Chuck Lever
     [not found]     ` <20090423233325.17283.71127.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-04-28 16:31       ` J. Bruce Fields
2009-04-28 16:36         ` Chuck Lever
2009-04-28 21:30           ` J. Bruce Fields
2009-04-23 23:33   ` [PATCH 18/19] lockd: Update NSM state from SM_MON replies Chuck Lever
     [not found]     ` <20090423233332.17283.23011.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-04-28 16:25       ` J. Bruce Fields
2009-04-28 16:34         ` Chuck Lever
2009-04-28 16:38           ` J. Bruce Fields
2009-04-28 19:11             ` Chuck Lever
2009-05-08 15:19               ` Chuck Lever
2009-05-08 15:33                 ` J. Bruce Fields
2009-04-23 23:33   ` [PATCH 19/19] lockd: clean up 64-bit alignment fix in nsm_init_private() Chuck Lever
     [not found]     ` <20090423233340.17283.29580.stgit-07a7zB5ZJzbwdl/1UfZZQIVfYA8g3rJ/@public.gmane.org>
2009-04-28 16:31       ` J. Bruce Fields
2009-04-28 16:35         ` Chuck Lever
2009-04-28 16:40           ` J. Bruce Fields
2009-04-28 17:24             ` Chuck Lever
2009-04-28 21:36               ` J. Bruce Fields
2009-04-28 22:03                 ` Måns Rullgård
     [not found]                   ` <yw1x63gozb9f.fsf-O+uoZmgXk1l54TAoqtyWWQ@public.gmane.org>
2009-04-28 22:14                     ` Chuck Lever
2009-04-28 22:11                 ` Chuck Lever
2009-04-28 22:23                   ` J. Bruce Fields
2009-04-28 22:31                   ` Måns Rullgård
     [not found]                     ` <yw1xws94xved.fsf-O+uoZmgXk1l54TAoqtyWWQ@public.gmane.org>
2009-04-28 22:43                       ` Chuck Lever
2009-04-28 22:52                         ` Måns Rullgård
     [not found]                           ` <yw1xskjsxuff.fsf-O+uoZmgXk1l54TAoqtyWWQ@public.gmane.org>
2009-04-29 15:16                             ` Chuck Lever
2009-04-29 18:02                               ` Måns Rullgård
2009-04-25 22:14   ` [PATCH 00/19] Proposed server-side patches for 2.6.31 J. Bruce Fields

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=20090427235644.GE5108@fieldses.org \
    --to=bfields@fieldses.org \
    --cc=chuck.lever@oracle.com \
    --cc=linux-nfs@vger.kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox