Bug 112775 - [libmd] [patch] libmd(3) bug for some zero-length files
Summary: [libmd] [patch] libmd(3) bug for some zero-length files
Status: Closed Overcome By Events
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 6.2-STABLE
Hardware: Any Any
: Normal Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-05-19 05:20 UTC by Ighighi
Modified: 2017-08-26 03:37 UTC (History)
1 user (show)

See Also:


Attachments
file.diff (543 bytes, patch)
2007-05-19 05:20 UTC, Ighighi
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Ighighi 2007-05-19 05:20:03 UTC
A bug was introduced into version 1.14 of src/lib/libmd/mdXhl.c that
prevents any application using the libmd(3) functions {MD4,MD5,SHA_,SHA1_,
SHA256_}File() from correctly processing zero-length files on filesystems
such as procfs(5).

Fix: The attached patch uses the code from the previous 1.13 version modified
for style(9).
To apply it on your system, run:
cd /usr/src/lib/libmd
make clean && make obj && make depend && make && make install


Patch attached with submission follows:
How-To-Repeat: $ /sbin/md5 /proc/1/cmdline
MD5 (/proc/1/cmdline) = d41d8cd98f00b204e9800998ecf8427e
$ /bin/cat /proc/1/cmdline | /sbin/md5
8624f652bec9bf7d9376dca7ea02a6b5
Comment 1 bde 2007-05-19 07:52:34 UTC
On Sat, 19 May 2007, Ighighi wrote:

>> Description:
> A bug was introduced into version 1.14 of src/lib/libmd/mdXhl.c that prevents any application using the libmd(3) functions {MD4,MD5,SHA_,SHA1_,SHA256_}File() from correctly processing zero-length files on filesystems such as procfs(5).

Please keep line lengths considerably shorter than 235 characters.

I've been waiting for many years for the author of the bug to fix this.
Not just the irregular regular zero-length files in procfs are broken
-- all files for which stat(2) doesn't report the file size are broken.
This includes all device files, and pipes.  For pipes, the bug is
normally not visible, since pipes are normally accessed via stdin and
then there is no filename on the command line so md5(1) uses its private
routine MDFilter() which is missing the bug.  The bug affects stdin too
if stdin is accessed by name (/dev/stdin or /dev/fd/0), at least when
/dev/stdin is actually a device on devfs.  I'm not sure what happens when
/dev/stdin is on fdescfs.

>> How-To-Repeat:
> $ /sbin/md5 /proc/1/cmdline
> MD5 (/proc/1/cmdline) = d41d8cd98f00b204e9800998ecf8427e
> $ /bin/cat /proc/1/cmdline | /sbin/md5
> 8624f652bec9bf7d9376dca7ea02a6b5

Piping the file as in the second command here is a workaround for most cases.

>> Fix:
>...
> --- lib/libmd/mdXhl.c.orig	Sun Sep  8 11:10:04 2002
> +++ lib/libmd/mdXhl.c	Sat May 19 00:04:24 2007
> @@ -43,7 +43,22 @@
> char *
> MDXFile(const char *filename, char *buf)
> {
> -	return (MDXFileChunk(filename, buf, 0, 0));
> +	unsigned char buffer[BUFSIZ];
> +	MDX_CTX ctx;
> +	int f, i, j;
> +
> +	MDXInit(&ctx);
> +	f = open(filename, O_RDONLY);
> +	if (f < 0)
> +		return 0;
> +	while ((i = read(f, buffer, sizeof(buffer))) > 0)
> +		MDXUpdate(&ctx, buffer, i);
> +	j = errno;
> +	close(f);
> +	errno = j;
> +	if (i < 0)
> +		return 0;
> +	return MDXEnd(&ctx, buf);
> }
>
> char *

This gives some duplication and leaves MDXFileChunk() unusuable.  Callers
of MDFileChunk() would have to either distrust MDXFileChunk() and never
call it, or call it and actually check for errors and decide which errors
are actually bugs in MDXFileChunk(), and work around the bugs...

Error handling is currently almost nonexistent.  MDXFileChunk() and
the above return NULL (spelled as 0) on error, but md5(1) never checks
for errors.  These routines at least distinguish between error and EOF.
The private MDFilter() doesn't even do that.

There is a minor API problem for handling the non-errors of EAGAIN and
EINTR.  If the application allows these (via non-blocking reads or
non-restarted syscalls after a signal), then it probably wants to
restart checksumming.  MDXFileChunk() provides a way, but only for
seekable files with a valid non-volatile size.  MDXFile() would have
to restart from the beginning, so it cannot work for pipes would take
too long or never complete for large regular files.  The restart needs
to be in the read loop to handle pipes, but restarting is not always
the correct handling, so the API would need a flag to control the
restart.  The stdio API has the same bug.

Bruce