util-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type
@ 2018-02-15 20:05 Theodore Ts'o
  2018-02-16  9:54 ` Karel Zak
  2018-02-16 15:55 ` Peter Cordes
  0 siblings, 2 replies; 7+ messages in thread
From: Theodore Ts'o @ 2018-02-15 20:05 UTC (permalink / raw)
  To: util-linux; +Cc: Hornseth_Brenan, Theodore Ts'o

This prevents a crash when running the command:

fsck -t AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /dev/sda

Reported-by: Hornseth_Brenan@bah.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
 disk-utils/fsck.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/disk-utils/fsck.c b/disk-utils/fsck.c
index 58fd8ac59..8a07bc272 100644
--- a/disk-utils/fsck.c
+++ b/disk-utils/fsck.c
@@ -544,20 +544,20 @@ static char *find_fsck(const char *type)
 {
 	char *s;
 	const char *tpl;
-	static char prog[256];
+	static char *prog = NULL;
 	char *p = xstrdup(fsck_path);
 
 	/* Are we looking for a program or just a type? */
 	tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
 
 	for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
-		sprintf(prog, tpl, s, type);
+		xasprintf(&prog, tpl, s, type);
 		if (access(prog, X_OK) == 0)
 			break;
+		free(prog); prog = NULL;
 	}
 	free(p);
-
-	return(s ? prog : NULL);
+	return(prog);
 }
 
 static int progress_active(void)
@@ -885,7 +885,7 @@ static int wait_many(int flags)
  */
 static int fsck_device(struct libmnt_fs *fs, int interactive)
 {
-	char progname[80], *progpath;
+	char *progname, *progpath;
 	const char *type;
 	int retval;
 
@@ -902,9 +902,10 @@ static int fsck_device(struct libmnt_fs *fs, int interactive)
 	else
 		type = DEFAULT_FSTYPE;
 
-	sprintf(progname, "fsck.%s", type);
+	xasprintf(&progname, "fsck.%s", type);
 	progpath = find_fsck(progname);
 	if (progpath == NULL) {
+		free(progname);
 		if (fs_check_required(type)) {
 			retval = ENOENT;
 			goto err;
@@ -914,6 +915,8 @@ static int fsck_device(struct libmnt_fs *fs, int interactive)
 
 	num_running++;
 	retval = execute(progname, progpath, type, fs, interactive);
+	free(progname);
+	free(progpath);
 	if (retval) {
 		num_running--;
 		goto err;
-- 
2.16.1.72.g5be1f00a9a


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type
  2018-02-15 20:05 [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type Theodore Ts'o
@ 2018-02-16  9:54 ` Karel Zak
  2018-02-16 15:55 ` Peter Cordes
  1 sibling, 0 replies; 7+ messages in thread
From: Karel Zak @ 2018-02-16  9:54 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: util-linux, Hornseth_Brenan

On Thu, Feb 15, 2018 at 03:05:08PM -0500, Theodore Ts'o wrote:
>  disk-utils/fsck.c | 15 +++++++++------
>  1 file changed, 9 insertions(+), 6 deletions(-)

Applied, thanks!

    Karel


-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type
  2018-02-15 20:05 [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type Theodore Ts'o
  2018-02-16  9:54 ` Karel Zak
@ 2018-02-16 15:55 ` Peter Cordes
  2018-02-16 17:10   ` Theodore Ts'o
  2018-02-16 18:08   ` Karel Zak
  1 sibling, 2 replies; 7+ messages in thread
From: Peter Cordes @ 2018-02-16 15:55 UTC (permalink / raw)
  To: Theodore Ts'o; +Cc: util-linux, Hornseth_Brenan

On Thu, Feb 15, 2018 at 03:05:08PM -0500, Theodore Ts'o wrote:
> This prevents a crash when running the command:
> 
> fsck -t AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /dev/sda
> 
> Reported-by: Hornseth_Brenan@bah.com
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> ---
>  disk-utils/fsck.c | 15 +++++++++------
>  1 file changed, 9 insertions(+), 6 deletions(-)
> 
> diff --git a/disk-utils/fsck.c b/disk-utils/fsck.c
> index 58fd8ac59..8a07bc272 100644
> --- a/disk-utils/fsck.c
> +++ b/disk-utils/fsck.c
> @@ -544,20 +544,20 @@ static char *find_fsck(const char *type)
>  {
>  	char *s;
>  	const char *tpl;
> -	static char prog[256];
> +	static char *prog = NULL;

 You're allocating / freeing every time it's used, so it shouldn't be
static anymore.

It might be easier to just use snprintf to truncate long strings,
instead of introducing dynamic allocation which requires explicit
freeing.  OTOH xasprintf makes it re-entrant / thread-safe, at the
cost of forcing the caller to care about memory management.  (And at
the cost of efficiency: prog is allocated / freed inside the loop.)

>  	char *p = xstrdup(fsck_path);
>  
>  	/* Are we looking for a program or just a type? */
>  	tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
>  
>  	for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
> -		sprintf(prog, tpl, s, type);
> +		xasprintf(&prog, tpl, s, type);
>  		if (access(prog, X_OK) == 0)
>  			break;
> +		free(prog); prog = NULL;
>  	}
>  	free(p);
> -
> -	return(s ? prog : NULL);
> +	return(prog);
>  }


-- 
#define X(x,y) x##y
Peter Cordes ;  e-mail: X(peter@cor , des.ca)

"The gods confound the man who first found out how to distinguish the hours!
 Confound him, too, who in this place set up a sundial, to cut and hack
 my day so wretchedly into small pieces!" -- Plautus, 200 BC

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type
  2018-02-16 15:55 ` Peter Cordes
@ 2018-02-16 17:10   ` Theodore Ts'o
  2018-02-16 18:08   ` Karel Zak
  1 sibling, 0 replies; 7+ messages in thread
From: Theodore Ts'o @ 2018-02-16 17:10 UTC (permalink / raw)
  To: Peter Cordes; +Cc: util-linux, Hornseth_Brenan

On Fri, Feb 16, 2018 at 11:55:05AM -0400, Peter Cordes wrote:
> > -	static char prog[256];
> > +	static char *prog = NULL;
> 
>  You're allocating / freeing every time it's used, so it shouldn't be
> static anymore.

Good point.  Karels has already accepted the patch, but if he hasn't
pushed it out, maybe he can ammend it.

> It might be easier to just use snprintf to truncate long strings,
> instead of introducing dynamic allocation which requires explicit
> freeing.  OTOH xasprintf makes it re-entrant / thread-safe, at the
> cost of forcing the caller to care about memory management.  (And at
> the cost of efficiency: prog is allocated / freed inside the loop.)

That's certainly an alternative, and in fact that's how I fixed it in
the old version of fsck still shipping in e2fsprogs (there are a few
places that still use it).

My main reason for using it there is that in e2fsprogs we don't assume
the use of xasprintf and family (it's a GNU extension, and e2fsprogs
tries to support legacy platforms such as MacOS and Windows :-).

However, given that fsck does use xasprintf already (and so there is
no portability advantag) and it's a lot easier to prove (or at least
satisfy to oneself) that an attacker who is trying to play tricks
can't do something unexpected when using xasprintf versus snprintf, I
went with asprintf in my patch to util-linux.

Cheers,

					- Ted

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type
  2018-02-16 15:55 ` Peter Cordes
  2018-02-16 17:10   ` Theodore Ts'o
@ 2018-02-16 18:08   ` Karel Zak
  2018-02-17  0:29     ` Peter Cordes
  2018-02-17  6:46     ` Theodore Ts'o
  1 sibling, 2 replies; 7+ messages in thread
From: Karel Zak @ 2018-02-16 18:08 UTC (permalink / raw)
  To: Peter Cordes; +Cc: Theodore Ts'o, util-linux, Hornseth_Brenan

On Fri, Feb 16, 2018 at 11:55:05AM -0400, Peter Cordes wrote:
> On Thu, Feb 15, 2018 at 03:05:08PM -0500, Theodore Ts'o wrote:
> > This prevents a crash when running the command:
> > 
> > fsck -t AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /dev/sda
> > 
> > Reported-by: Hornseth_Brenan@bah.com
> > Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> > ---
> >  disk-utils/fsck.c | 15 +++++++++------
> >  1 file changed, 9 insertions(+), 6 deletions(-)
> > 
> > diff --git a/disk-utils/fsck.c b/disk-utils/fsck.c
> > index 58fd8ac59..8a07bc272 100644
> > --- a/disk-utils/fsck.c
> > +++ b/disk-utils/fsck.c
> > @@ -544,20 +544,20 @@ static char *find_fsck(const char *type)
> >  {
> >  	char *s;
> >  	const char *tpl;
> > -	static char prog[256];
> > +	static char *prog = NULL;
> 
>  You're allocating / freeing every time it's used, so it shouldn't be
> static anymore.

Ah, I miss the "static". Thanks.

> It might be easier to just use snprintf to truncate long strings,
> instead of introducing dynamic allocation which requires explicit
> freeing.  OTOH xasprintf makes it re-entrant / thread-safe, at the
> cost of forcing the caller to care about memory management.  (And at
> the cost of efficiency: prog is allocated / freed inside the loop.)

Well, I don't think dynamic allocation so big issue in this case, but
I'll try to improve it on Monday to make the code more elegant.

Maybe all we need is to check -t argument and reject non-senses
already in main() ;-)

    Karel

-- 
 Karel Zak  <kzak@redhat.com>
 http://karelzak.blogspot.com

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type
  2018-02-16 18:08   ` Karel Zak
@ 2018-02-17  0:29     ` Peter Cordes
  2018-02-17  6:46     ` Theodore Ts'o
  1 sibling, 0 replies; 7+ messages in thread
From: Peter Cordes @ 2018-02-17  0:29 UTC (permalink / raw)
  To: Karel Zak; +Cc: Theodore Ts'o, util-linux, Hornseth_Brenan

On Fri, Feb 16, 2018 at 07:08:20PM +0100, Karel Zak wrote:
> On Fri, Feb 16, 2018 at 11:55:05AM -0400, Peter Cordes wrote:
> > On Thu, Feb 15, 2018 at 03:05:08PM -0500, Theodore Ts'o wrote:
> > > This prevents a crash when running the command:
> > > 
> > > fsck -t AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /dev/sda
> > > 
> > > Reported-by: Hornseth_Brenan@bah.com
> > > Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> > > ---
> > >  disk-utils/fsck.c | 15 +++++++++------
> > >  1 file changed, 9 insertions(+), 6 deletions(-)
> > > 
> > > diff --git a/disk-utils/fsck.c b/disk-utils/fsck.c
> > > index 58fd8ac59..8a07bc272 100644
> > > --- a/disk-utils/fsck.c
> > > +++ b/disk-utils/fsck.c
> > > @@ -544,20 +544,20 @@ static char *find_fsck(const char *type)
> > >  {
> > >  	char *s;
> > >  	const char *tpl;
> > > -	static char prog[256];
> > > +	static char *prog = NULL;
> > 
> >  You're allocating / freeing every time it's used, so it shouldn't be
> > static anymore.
> 
> Ah, I miss the "static". Thanks.
> 
> > It might be easier to just use snprintf to truncate long strings,
> > instead of introducing dynamic allocation which requires explicit
> > freeing.  OTOH xasprintf makes it re-entrant / thread-safe, at the
> > cost of forcing the caller to care about memory management.  (And at
> > the cost of efficiency: prog is allocated / freed inside the loop.)
> 
> Well, I don't think dynamic allocation so big issue in this case, but
> I'll try to improve it on Monday to make the code more elegant.
> 
> Maybe all we need is to check -t argument and reject non-senses
> already in main() ;-)

Ted makes a good point that xasprintf makes it easier to reason about
correctness, and that's probably the most important consideration for
FSCK.  This code hardly needs to be efficient, and malloc/free aren't
terrible especially in a single-threaded program.

OTOH, I was worried for a while about a possible memory leak until I
figured out that leaving the loop without freeing was intentional, and
it was returning that memory to the caller.  (Of course it does;
that's the whole point of the function; but still,  if() break; before
free() looked worrying.)

---

If your proposed check in main() is based on length, then static buffer
size should probably also be set in main, otherwise you have magic
constants in two places that have to match.

Maybe have main() pass in a pointer + size for find_fsck to write
into (using snprintf)?

-- 
#define X(x,y) x##y
Peter Cordes ;  e-mail: X(peter@cor , des.ca)

"The gods confound the man who first found out how to distinguish the hours!
 Confound him, too, who in this place set up a sundial, to cut and hack
 my day so wretchedly into small pieces!" -- Plautus, 200 BC

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type
  2018-02-16 18:08   ` Karel Zak
  2018-02-17  0:29     ` Peter Cordes
@ 2018-02-17  6:46     ` Theodore Ts'o
  1 sibling, 0 replies; 7+ messages in thread
From: Theodore Ts'o @ 2018-02-17  6:46 UTC (permalink / raw)
  To: Karel Zak; +Cc: Peter Cordes, util-linux, Hornseth_Brenan

On Fri, Feb 16, 2018 at 07:08:20PM +0100, Karel Zak wrote:
> 
> Maybe all we need is to check -t argument and reject non-senses
> already in main() ;-)

I also thought about rejecting any file system type larger than, say,
16 characters.  Then I looked at the kernel code, and in theory
there's nothing stopping someone from creating an out-of-tree kernel
file system with a file system type of, say, for example:

	supercalifragilisticexpialidocious

:-)

					- Ted

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2018-02-17  6:47 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-15 20:05 [PATCH] fsck: use xasprintf to avoid buffer overruns with an insane fs type Theodore Ts'o
2018-02-16  9:54 ` Karel Zak
2018-02-16 15:55 ` Peter Cordes
2018-02-16 17:10   ` Theodore Ts'o
2018-02-16 18:08   ` Karel Zak
2018-02-17  0:29     ` Peter Cordes
2018-02-17  6:46     ` Theodore Ts'o

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).