qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] linux-user: allow to use sudo in guest


From: Laurent Vivier
Subject: Re: [Qemu-devel] [PATCH] linux-user: allow to use sudo in guest
Date: Sun, 27 Jan 2013 02:56:59 +0100

In fact, this patch is useless as binfmt_mist provides a flag to manage
credentials and security token.

A new patch follows...

Regards,
Laurent

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) :
> 
>     address@hidden $ id
>     uid=1000(laurent) gid=1000(laurent) groups=1000(laurent)
>     address@hidden $ sudo id
>     Password:
>     uid=0(root) gid=0(root) groups=0(root)
> 
> - check LD_PRELOAD is available (debian fakeroot is my testcase) :
> 
>     address@hidden $ fakeroot id
>     uid=0(root) gid=0(root) groups=1000(laurent)
>     address@hidden $ rm -f toto
>     address@hidden $ fakeroot
>     address@hidden # touch toto
>     address@hidden # ls -l toto
>     -rw-r--r-- 1 root root 0 2012-12-18 22:50 toto
>     address@hidden # exit
>     exit
>     address@hidden # ls -l toto
>     -rw-r--r-- 1 laurent laurent 0 2012-12-18 22:50 toto
> 
> Signed-off-by: Laurent Vivier <address@hidden>
> ---
>  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 via email to

[Prev in Thread] Current Thread [Next in Thread]