[arch-projects] [mkinitcpio] [RFC] Rewrite parse_cmdline (again)

Dave Reisner d at falconindy.com
Thu Apr 14 20:24:06 EDT 2011


On Fri, Apr 15, 2011 at 12:13:29AM +0200, Rémy Oudompheng wrote:
> On Thu 14 April 2011 at 17:44 -0400, dave reisner wrote:
> > On Apr 14, 2011 5:28 PM, "Thomas Bächler" <thomas at archlinux.org> wrote:
> > > > I posted what I thought was a valid solution on FS#23467 from stack
> > > > overflow that seems to be a lot more sane and _much_ more maintainable.
> > > > For those who weren't following the report, I suggested that we use the
> > > > same fallback as /etc/fstab, which says to encode spaces with octal
> > > > sequences. These can then be decoded using printf's %b flag. It requires
> > > > only a simple change to the current parse_cmdline function.
> > >
> > > I really don't understand what you mean (or how it would help). What you
> > > mentioned doesn't solve the initial problem of finding out which spaces
> > > separate arguments and which spaces are inside quoted strings.
> > >
> > 
> > It absolutely does because it eliminates spaces within variables, e.g.
> > video=foo\040bar root=…
> > 
> > The whole point is that quotes aren't used. fstab sets precedent here so its
> > not some wild and whacky new thing being introduced.
> 
> This looks very nice, but how do we get a space-escaped kernel command
> line? Is the user expected to encode his command line at boot time?
> 
> And do we really have to filter out invalid variable names? Isn't there
> some documentation that says the kernel isn't supposed to have absurd
> command line parameters (like unescaped >, <, &, |)
> 
> Because I think that (minus eval statements), the function would look
> better like this :
> 
> local w lhs rhs
> eval set -- $(cat test)
> for w; do
>     case "${w}" in
>         \#*) break ;; # ignore everything after a # in the commandline
>         # The kernel passes those to init on its own
>         [0123456Ss]) ;;
>         single) ;;
>         rw) readwrite="yes" ;;
>         ro) readwrite="no" ;;
>         # variables don't begin with a digit
>         [0-9]*) ;;
>         # only export stuff that does work with ash :)
>         *=*)
>             lhs=${w%%=*}
>             rhs=${w#*=}
>             # replace forbidden characters
>             lhs=${lhs/./_}
>             lhs=${lhs/-/_}
>             eval "${lhs}='${rhs}'"
>             ;;
>         *)
>             lhs=${w/./_}
>             lhs=${w/-/_}
>             eval "${lhs}=y"
>             ;;
>     esac
> done
> 
> -- 
> Rémy.

Yes, the idea is that the user is expected to escape their own
whitespace, just as they are expected to do so in /etc/fstab. I tested
the following across the open bug reports and can report great success
on all fronts:

parse_cmdline() {
  for cmd in $(cat /proc/cmdline); do
    case $cmd in
      \#*) break ;; # ignore everything after a # in the commandline
      # The kernel passes those to the kernel on its own
      [0123456Ss]) ;;
      [0-9]*) ;;
      single) ;;
      rw) readwrite="yes" ;;
      ro) readwrite="no" ;;
      # only export stuff that does work with ash :)
      *=*) lhs=${cmd%%=*}
           lhs=${lhs//[-.]/_}
           rhs=$(printf '%b' "${cmd#*=}")
           export "$lhs"="$rhs"
           ;;
      *) cmd=${cmd//[-.]/_}
         export "$cmd"="y"
         ;;
    esac
  done
}

Yes, I've also removed the grep checks prior to each export. They're
redundant because of the 3rd case down, [0-9]*, already checking for a
variable starting with a leading digit.

Thomas mentioned in IRC that there was a "huge problem" with this, but
had to go to sleep. I'm interested in what he has to say.

dave



More information about the arch-projects mailing list