qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Laurent Vivier <Laurent@vivier.eu>
To: qemu-devel@nongnu.org
Cc: Riku Voipio <riku.voipio@iki.fi>
Subject: Re: [Qemu-devel] [PATCH] linux-user: allow to use sudo in guest
Date: Wed, 02 Jan 2013 00:09:52 +0100	[thread overview]
Message-ID: <1357081792.31530.8.camel@Quad> (raw)
In-Reply-To: <1356037019-19426-1-git-send-email-laurent@vivier.eu>

Ping !

Le jeudi 20 décembre 2012 à 21:56 +0100, Laurent Vivier a écrit :
> When qemu-linux-user is used in a linux container or chroot,
> if it needs to load binaries with SUID/SGID bits, it needs to
> have root rights to be able to change UID/GID. To do that, we
> need to install it with SUID bits and root owner.
> Then, if the SUID bit is not set on the binary to load,
> qemu will set its UID to the saved UID (the current user ID).
> 
> To be able to retrieve unsecure environment variables (LD_PRELOAD,
> LD_LIBRARY_PATH) with SUID bit, we need to disable "unsetenv()".
> Otherwise libc unsets these variables before entering in main()
> 
> To enable this feature, add "--suid-able" to the configure parameters.
> 
> You can check all is working fine with :
> 
> - install qemu-<arch> in your <arch> root filesystem environment
>   and chown root:root ... and chmow +s ...
> 
> - check sudo in this environment (chroot or linux container) :
> 
>     laurent@m68k $ id
>     uid=1000(laurent) gid=1000(laurent) groups=1000(laurent)
>     laurent@m68k $ sudo id
>     Password:
>     uid=0(root) gid=0(root) groups=0(root)
> 
> - check LD_PRELOAD is available (debian fakeroot is my testcase) :
> 
>     laurent@m68k $ fakeroot id
>     uid=0(root) gid=0(root) groups=1000(laurent)
>     laurent@m68k $ rm -f toto
>     laurent@m68k $ fakeroot
>     root@m68k # touch toto
>     root@m68k # ls -l toto
>     -rw-r--r-- 1 root root 0 2012-12-18 22:50 toto
>     root@m68k # exit
>     exit
>     root@m68k # ls -l toto
>     -rw-r--r-- 1 laurent laurent 0 2012-12-18 22:50 toto
> 
> Signed-off-by: Laurent Vivier <laurent@vivier.eu>
> ---
>  configure              |   15 +++++++++++++++
>  linux-user/linuxload.c |   16 +++++++++++-----
>  linux-user/main.c      |   20 ++++++++++++++++++++
>  3 files changed, 46 insertions(+), 5 deletions(-)
> 
> diff --git a/configure b/configure
> index b101d5c..2322387 100755
> --- a/configure
> +++ b/configure
> @@ -111,6 +111,7 @@ source_path=`dirname "$0"`
>  cpu=""
>  interp_prefix="/usr/gnemul/qemu-%M"
>  static="no"
> +suidable="no"
>  cross_prefix=""
>  audio_drv_list=""
>  audio_card_list="ac97 es1370 sb16 hda"
> @@ -624,6 +625,9 @@ for opt do
>      LDFLAGS="-static $LDFLAGS"
>      QEMU_PKG_CONFIG_FLAGS="--static $QEMU_PKG_CONFIG_FLAGS"
>    ;;
> +  --suid-able)
> +    suidable="yes"
> +  ;;
>    --mandir=*) mandir="$optarg"
>    ;;
>    --bindir=*) bindir="$optarg"
> @@ -885,6 +889,11 @@ for opt do
>    esac
>  done
>  
> +if test "$suidable" = "yes" -a "$static" = "no" ; then
> +    echo "ERROR: --suid-able needs --static"
> +    exit 1
> +fi
> +
>  case "$cpu" in
>      sparc)
>             LDFLAGS="-m32 $LDFLAGS"
> @@ -1014,6 +1023,7 @@ echo "  --install=INSTALL        use specified install [$install]"
>  echo "  --python=PYTHON          use specified python [$python]"
>  echo "  --smbd=SMBD              use specified smbd [$smbd]"
>  echo "  --static                 enable static build [$static]"
> +echo "  --suid-able              allow to use qemu with SUID bit [$suidable]"
>  echo "  --mandir=PATH            install man pages in PATH"
>  echo "  --datadir=PATH           install firmware in PATH$confsuffix"
>  echo "  --docdir=PATH            install documentation in PATH$confsuffix"
> @@ -3196,6 +3206,7 @@ echo "sparse enabled    $sparse"
>  echo "strip binaries    $strip_opt"
>  echo "profiler          $profiler"
>  echo "static build      $static"
> +echo "suid-able         $suidable"
>  echo "-Werror enabled   $werror"
>  if test "$darwin" = "yes" ; then
>      echo "Cocoa support     $cocoa"
> @@ -4160,6 +4171,10 @@ if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
>      ;;
>    esac
>  fi
> +if test "$target_linux_user" = "yes" -a "$suidable" = "yes" ; then
> +  ldflags="$ldflags -Wl,--wrap=__unsetenv"
> +  echo "CONFIG_SUIDABLE=y"  >> $config_target_mak
> +fi
>  
>  echo "LDFLAGS+=$ldflags" >> $config_target_mak
>  echo "QEMU_CFLAGS+=$cflags" >> $config_target_mak
> diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c
> index 381ab89..783afce 100644
> --- a/linux-user/linuxload.c
> +++ b/linux-user/linuxload.c
> @@ -58,11 +58,6 @@ static int prepare_binprm(struct linux_binprm *bprm)
>      bprm->e_uid = geteuid();
>      bprm->e_gid = getegid();
>  
> -    /* Set-uid? */
> -    if(mode & S_ISUID) {
> -    	bprm->e_uid = st.st_uid;
> -    }
> -
>      /* Set-gid? */
>      /*
>       * If setgid is set but no group execute bit then this
> @@ -72,6 +67,17 @@ static int prepare_binprm(struct linux_binprm *bprm)
>      if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
>  	bprm->e_gid = st.st_gid;
>      }
> +#if defined(CONFIG_SUIDABLE)
> +    setresgid(getgid(), bprm->e_gid, bprm->e_gid);
> +#endif
> +
> +    /* Set-uid? */
> +    if(mode & S_ISUID) {
> +    	bprm->e_uid = st.st_uid;
> +    }
> +#if defined(CONFIG_SUIDABLE)
> +    setresuid(getuid(), bprm->e_uid, bprm->e_uid);
> +#endif
>  
>      retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE);
>      if (retval < 0) {
> diff --git a/linux-user/main.c b/linux-user/main.c
> index f6c4c8d..dd9dd24 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -3385,6 +3385,20 @@ static int parse_args(int argc, char **argv)
>      return optind;
>  }
>  
> +#if defined(CONFIG_SUIDABLE)
> +static int allow_unsetenv = 0;
> +
> +int __wrap___unsetenv(const char *name);
> +int __real___unsetenv(const char *name);
> +int
> +__wrap___unsetenv(const char *name)
> +{
> +    if (!allow_unsetenv)
> +        return 0;
> +    return __real___unsetenv(name);
> +}
> +#endif
> +
>  int main(int argc, char **argv, char **envp)
>  {
>      const char *log_file = DEBUG_LOGFILE;
> @@ -3400,6 +3414,12 @@ int main(int argc, char **argv, char **envp)
>      int i;
>      int ret;
>  
> +#if defined(CONFIG_SUIDABLE)
> +    allow_unsetenv = 1;
> +    seteuid(getuid());
> +    setegid(getgid());
> +#endif
> +
>      module_call_init(MODULE_INIT_QOM);
>  
>      qemu_cache_utils_init(envp);

-- 
"Just play. Have fun. Enjoy the game."
- Michael Jordan
"Just play. Have fun. Enjoy the game."
- Michael Jordan

  reply	other threads:[~2013-01-01 23:09 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-12-20 20:56 [Qemu-devel] [PATCH] linux-user: allow to use sudo in guest Laurent Vivier
2013-01-01 23:09 ` Laurent Vivier [this message]
2013-01-02  1:16 ` Peter Maydell
2013-01-02 19:37   ` Laurent Vivier

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=1357081792.31530.8.camel@Quad \
    --to=laurent@vivier.eu \
    --cc=qemu-devel@nongnu.org \
    --cc=riku.voipio@iki.fi \
    /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.
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).