From: Ismael Luceno <ismael@iodev.co.uk>
To: musl@lists.openwall.com
Subject: Re: [PATCH] glob: implement GLOB_TILDE
Date: Wed, 24 Jul 2019 09:15:22 +0200 [thread overview]
Message-ID: <20190724071522.GA24370@pirotess.home> (raw)
In-Reply-To: <20190723200708.GA25787@brightrain.aerifal.cx>
On 23/Jul/2019 16:07, Rich Felker wrote:
> On Tue, Jul 23, 2019 at 08:33:54PM +0200, Ismael Luceno wrote:
> > Signed-off-by: Ismael Luceno <ismael@iodev.co.uk>
> > ---
> > include/glob.h | 1 +
> > src/regex/glob.c | 26 ++++++++++++++++++++++++++
> > 2 files changed, 27 insertions(+)
> >
> > diff --git a/include/glob.h b/include/glob.h
> > index 76f6c1c68a23..fc8106b20c5b 100644
> > --- a/include/glob.h
> > +++ b/include/glob.h
> > @@ -30,6 +30,7 @@ void globfree(glob_t *);
> > #define GLOB_APPEND 0x20
> > #define GLOB_NOESCAPE 0x40
> > #define GLOB_PERIOD 0x80
> > +#define GLOB_TILDE 0x100
> >
> > #define GLOB_NOSPACE 1
> > #define GLOB_ABORTED 2
> > diff --git a/src/regex/glob.c b/src/regex/glob.c
> > index aa1c6a4482ee..77b81f707420 100644
> > --- a/src/regex/glob.c
> > +++ b/src/regex/glob.c
> > @@ -8,6 +8,8 @@
> > #include <stdlib.h>
> > #include <errno.h>
> > #include <stddef.h>
> > +#include <unistd.h>
> > +#include "../passwd/pwf.h"
> >
> > struct match
> > {
> > @@ -35,6 +37,30 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (*
> > /* If GLOB_MARK is unused, we don't care about type. */
> > if (!type && !(flags & GLOB_MARK)) type = DT_REG;
> >
> > + if ((flags & GLOB_TILDE) && *pat == '~') {
> > + struct passwd pw, *res;
> > + char *buf = NULL;
> > + size_t len = 0;
> > + char *name_end = strchr(++pat, '/');
> > + if (name_end)
> > + *name_end = 0;
> > + uid_t uid = *pat ? 0 : getuid();
> > + int err = __getpw_a(pat, uid, &pw, &buf, &len, &res);
> > + if (!err && res) {
> > + while (pos < PATH_MAX - 1 && *pw.pw_dir)
> > + buf[pos++] = *pw.pw_dir++;
> > + }
> > + free(buf);
> > + if (err)
> > + return GLOB_NOSPACE;
> > + if (!res)
> > + return 0;
> > + if (name_end) {
> > + pat = name_end;
> > + *pat = '/';
> > + }
> > + }
>
> This should almost surely go in the top-level glob function rather
> than the recusive function, where the original strdup of pat happens.
> As you've written it, I think it wrongly applies tilde expansion to
> each path component into which recursion happens, but not to ones
> where it doesn't, whereas it should only apply to the first component.
> Doing this in the recursive function also has the problem of exploding
> stack usage. One thing I don't see is how the code is working at all
> right now, because you've shadowed the argument buf with a locally
> scoped variable by the same name that's the working space buffer
> passed to __getpw_a. The result directory is never copied out into the
> actual buf array.
Indeed it doesn't work XD.
I meant it more as a quick try and to see if it was interesting and the
right kind of approach.
Though I forgot to add "RFC" to the subject prefix.
> One thing to note at this point: it's generally preferable to use the
> public interfaces (getpwnam_r) rather than the internal ones from a
> different sybsystem of libc (__getpw_a) unless there's a really
> compelling reason not to. Here I think it would actually be easier
> using the public interface -- you could reuse buf for the buffer space
> you pass to getpwnam_r, then memmove from pw_dir (which lies somewhere
> inside buf, you don't know where) to the start of buf.
The reason I had to use the private interface is to avoid dealing with
the buffer allocation on the side of the glob function.
It would be better to keep it that way.
> There's also a matter of intended behavor: my understanding is that
> plain ~ without a name is supposed to expand to $HOME, not lookup the
> caller's passwd entry based on uid (which is broken on setups where
> you have multiple login accounts with the same uid). The man page
> doesn't document this at all. I looked just now in the glibc manual
> and it documents the behavior in terms of getlogin+getpwnam, which is
> utterly broken -- it doesn't work at all in the absence of a login
> session associated with a terminal (except in musl where we wrongly
> just return getenv("LOGNAME"), a known/open bug). and it's also
> inconsistent with the standard shell behavior, which is to use $HOME:
>
> http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_01
>
> So I feel like, if we implement GLOB_TILDE, we should do it the way
> that's consistent with the standard meaning of ~, using $HOME, not the
> glibc implementation. This is also much more user-friendly, in that it
> honors manual override of $HOME.
I'm not entirely comfortable expanding HOME unconditionally, as it could
easily be exploited into a vulnerability for any privileged (e.g.
setuid) process.
Thank you very much for your comments; I will try to come up with a
better version later today.
next prev parent reply other threads:[~2019-07-24 7:15 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-07-23 18:33 Ismael Luceno
2019-07-23 20:07 ` Rich Felker
2019-07-24 7:15 ` Ismael Luceno [this message]
2019-07-24 13:00 ` Rich Felker
2019-07-24 17:25 ` Ismael Luceno
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=20190724071522.GA24370@pirotess.home \
--to=ismael@iodev.co.uk \
--cc=musl@lists.openwall.com \
/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.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/musl/
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).