Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Wed, 17 Jun 2015 14:07:08 -0500
From: Josiah Worcester <josiahw@...il.com>
To: musl@...ts.openwall.com, Josiah Worcester <josiahw@...il.com>
Subject: Re: [PATCH] Implement glibc *_chk interfaces for ABI compatibility.

On Wed, Jun 17, 2015 at 4:30 AM, Szabolcs Nagy <nsz@...t70.net> wrote:
> * Josiah Worcester <josiahw@...il.com> [2015-06-16 21:48:11 -0500]:
>> --- /dev/null
>> +++ b/src/compat/gnu_chk.c
>> @@ -0,0 +1,18 @@
>> +#define _GNU_SOURCE
>> +#include <string.h>
>> +#include <poll.h>
>> +#include <stddef.h>
>> +#include "atomic.h"
>> +#include "atomic.h"
>> +
>> +int __ppoll_chk(struct pollfd *fds, nfds_t n, const struct timespec *to, const sigset_t *mask, size_t fdslen)
>> +{
>> +     if (fdslen / sizeof(*fds) < n) a_crash();
>> +     return ppoll(fds, n, to, mask);
>> +}
>> +
>> +void *__mempcpy_chk(void *dest, const void *src, size_t n, size_t destlen)
>> +{
>> +     if (destlen < n) a_crash();
>> +     return mempcpy(dest, src, n);
>> +}
>
> one atomic is enough
>

Ooops.

>> +char *__gets_chk(char *buf, size_t size)
>> +{
>> +     char *ret = buf;
>> +     int c;
>> +     FLOCK(stdin);
>> +     if (!size) return NULL;
>> +     for(;size;buf++,size--) {
>> +             c = getc(stdin);
>> +             if ((c == EOF && feof(stdin)) || c == '\n') {
>> +                     *buf = 0;
>> +                     FUNLOCK(stdin);
>> +                     return ret;
>> +             }
>> +             if (c == EOF) {
>> +                     FUNLOCK(stdin);
>> +                     return NULL;
>> +             }
>> +             *buf = c;
>> +     }
>> +     a_crash();
>> +}
>
> this looks wrong if !size
>
> i think that line should be just removed
>

Hmm, yeah.  When the buffer is empty it should crash, not just report error.

>> +void *__memmove_chk(void *restrict dest, const void *restrict src, size_t n, size_t destlen)
>> +{
>> +     if (n > destlen) a_crash();
>> +     return memmove(dest, src, n);
>> +}
>
> i think restrict is wrong here
>

It is.

>> +char *__strcat_chk(char *restrict dest, const char *restrict src, size_t destlen)
>> +{
>> +     size_t tot;
>> +     tot = strnlen(src, destlen);
>> +     if (tot > SIZE_MAX - strnlen(dest, destlen) - 1) a_crash();
>> +     tot += strnlen(dest, destlen) + 1;
>> +     if (tot > destlen) a_crash();
>> +     return strcat(dest, src);
>> +}
>> +
>> +char *__strncat_chk(char *restrict dest, const char *restrict src, size_t n, size_t destlen)
>> +{
>> +     size_t tot;
>> +     tot = strnlen(dest, destlen);
>> +     if (tot > SIZE_MAX - strnlen(src, n) - 1) a_crash();
>> +     tot += strnlen(src, n) + 1;
>> +     if (tot > destlen) a_crash();
>> +     return strncat(dest, src, n);
>> +}
>> +
>
> i'd store the strnlen result in a temporary var
>
> musl is built with -ffreestanding so the compiler cannot
> assume strnlen is a pure function.

Good call. In common use it won't matter much, but that's potentially
an extra string iteration for no good reason.

>> +wchar_t *__wcscat_chk(wchar_t *restrict dest, const wchar_t *src, size_t destlen)
>> +{
>> +     size_t tot;
>> +     tot = wcsnlen(src, destlen);
>> +     if (tot > SIZE_MAX - wcsnlen(dest, destlen) - 1) a_crash();
>> +     tot += wcsnlen(dest, destlen) + 1;
>> +     if (tot > destlen) a_crash();
>> +     return wcscat(dest, src);
>> +}
>> +
>> +wchar_t *__wcsncat_chk(wchar_t *restrict dest, const wchar_t *restrict src, size_t n, size_t destlen)
>> +{
>> +     size_t tot;
>> +     tot = wcsnlen(dest, destlen);
>> +     if (tot > SIZE_MAX - wcsnlen(src, n) - 1) a_crash();
>> +     tot += wcsnlen(dest, destlen) + 1;
>> +     if (tot > destlen) a_crash();
>> +     return wcsncat(dest, src, n);
>> +}
>> +
>
> ditto
>
>> diff --git a/src/compat/ttyname_r_chk.c b/src/compat/ttyname_r_chk.c
>> new file mode 100644
>> index 0000000..50e70e5
>> --- /dev/null
>> +++ b/src/compat/ttyname_r_chk.c
>> @@ -0,0 +1,7 @@
>> +#include <unistd.h>
>> +
>> +int __ttyname_r_chk(int fd, char *name, size_t size, size_t namelen)
>> +{
>> +     if (size > namelen) a_crash();
>> +     return ttyname_r(fd, name, size);
>> +}
>
> missing atomic.h for a_crash

Oops.

> shouldnt this be in posix_chk.c?

This... I swear I deleted this file before making the patch. It's an
old development fragment. The one I actually care about is in
posix_chk.c.

>> +size_t __wcrtomb_chk(char *restrict s, wchar_t wc, mbstate_t *restrict st, size_t slen)
>> +{
>> +     if (slen < MB_CUR_MAX) a_crash();
>> +     return wcrtomb(s, wc, st);
>> +}
>
> i think this can cause a false positive crash
> but glibc seems to do the same..
>
> (eg some api passes wchar_t* and the exact mb encoded length of
> a string so the output s can be safely shorter than max mb length)
>
I'm not sure if we should match glibc here or do a better check.

Thanks for the input. I'm going to wait a bit before posting a new
patch, though, in hopes that more comments are forthcoming.

Powered by blists - more mailing lists

Your e-mail address:

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.