From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:48222) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TqAy6-0000D5-2H for qemu-devel@nongnu.org; Tue, 01 Jan 2013 18:09:59 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TqAy4-00087K-Cv for qemu-devel@nongnu.org; Tue, 01 Jan 2013 18:09:57 -0500 Received: from moutng.kundenserver.de ([212.227.17.9]:63449) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TqAy4-00087E-2r for qemu-devel@nongnu.org; Tue, 01 Jan 2013 18:09:56 -0500 Message-ID: <1357081792.31530.8.camel@Quad> From: Laurent Vivier Date: Wed, 02 Jan 2013 00:09:52 +0100 In-Reply-To: <1356037019-19426-1-git-send-email-laurent@vivier.eu> References: <1356037019-19426-1-git-send-email-laurent@vivier.eu> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable Subject: Re: [Qemu-devel] [PATCH] linux-user: allow to use sudo in guest List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Riku Voipio Ping ! Le jeudi 20 d=C3=A9cembre 2012 =C3=A0 21:56 +0100, Laurent Vivier a =C3=A9c= rit : > 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). >=20 > 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() >=20 > To enable this feature, add "--suid-able" to the configure parameters. >=20 > You can check all is working fine with : >=20 > - install qemu- in your root filesystem environment > and chown root:root ... and chmow +s ... >=20 > - check sudo in this environment (chroot or linux container) : >=20 > laurent@m68k $ id > uid=3D1000(laurent) gid=3D1000(laurent) groups=3D1000(laurent) > laurent@m68k $ sudo id > Password: > uid=3D0(root) gid=3D0(root) groups=3D0(root) >=20 > - check LD_PRELOAD is available (debian fakeroot is my testcase) : >=20 > laurent@m68k $ fakeroot id > uid=3D0(root) gid=3D0(root) groups=3D1000(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 >=20 > Signed-off-by: Laurent Vivier > --- > configure | 15 +++++++++++++++ > linux-user/linuxload.c | 16 +++++++++++----- > linux-user/main.c | 20 ++++++++++++++++++++ > 3 files changed, 46 insertions(+), 5 deletions(-) >=20 > diff --git a/configure b/configure > index b101d5c..2322387 100755 > --- a/configure > +++ b/configure > @@ -111,6 +111,7 @@ source_path=3D`dirname "$0"` > cpu=3D"" > interp_prefix=3D"/usr/gnemul/qemu-%M" > static=3D"no" > +suidable=3D"no" > cross_prefix=3D"" > audio_drv_list=3D"" > audio_card_list=3D"ac97 es1370 sb16 hda" > @@ -624,6 +625,9 @@ for opt do > LDFLAGS=3D"-static $LDFLAGS" > QEMU_PKG_CONFIG_FLAGS=3D"--static $QEMU_PKG_CONFIG_FLAGS" > ;; > + --suid-able) > + suidable=3D"yes" > + ;; > --mandir=3D*) mandir=3D"$optarg" > ;; > --bindir=3D*) bindir=3D"$optarg" > @@ -885,6 +889,11 @@ for opt do > esac > done > =20 > +if test "$suidable" =3D "yes" -a "$static" =3D "no" ; then > + echo "ERROR: --suid-able needs --static" > + exit 1 > +fi > + > case "$cpu" in > sparc) > LDFLAGS=3D"-m32 $LDFLAGS" > @@ -1014,6 +1023,7 @@ echo " --install=3DINSTALL use specified in= stall [$install]" > echo " --python=3DPYTHON use specified python [$python]" > echo " --smbd=3DSMBD use specified smbd [$smbd]" > echo " --static enable static build [$static]" > +echo " --suid-able allow to use qemu with SUID bit [$suida= ble]" > echo " --mandir=3DPATH install man pages in PATH" > echo " --datadir=3DPATH install firmware in PATH$confsuffix" > echo " --docdir=3DPATH install documentation in PATH$confsuf= fix" > @@ -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" =3D "yes" ; then > echo "Cocoa support $cocoa" > @@ -4160,6 +4171,10 @@ if test "$target_linux_user" =3D "yes" -o "$target= _bsd_user" =3D "yes" ; then > ;; > esac > fi > +if test "$target_linux_user" =3D "yes" -a "$suidable" =3D "yes" ; then > + ldflags=3D"$ldflags -Wl,--wrap=3D__unsetenv" > + echo "CONFIG_SUIDABLE=3Dy" >> $config_target_mak > +fi > =20 > echo "LDFLAGS+=3D$ldflags" >> $config_target_mak > echo "QEMU_CFLAGS+=3D$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 =3D geteuid(); > bprm->e_gid =3D getegid(); > =20 > - /* Set-uid? */ > - if(mode & S_ISUID) { > - bprm->e_uid =3D 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)) =3D=3D (S_ISGID | S_IXGRP)) { > bprm->e_gid =3D 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 =3D st.st_uid; > + } > +#if defined(CONFIG_SUIDABLE) > + setresuid(getuid(), bprm->e_uid, bprm->e_uid); > +#endif > =20 > retval =3D 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; > } > =20 > +#if defined(CONFIG_SUIDABLE) > +static int allow_unsetenv =3D 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 =3D DEBUG_LOGFILE; > @@ -3400,6 +3414,12 @@ int main(int argc, char **argv, char **envp) > int i; > int ret; > =20 > +#if defined(CONFIG_SUIDABLE) > + allow_unsetenv =3D 1; > + seteuid(getuid()); > + setegid(getgid()); > +#endif > + > module_call_init(MODULE_INIT_QOM); > =20 > qemu_cache_utils_init(envp); --=20 "Just play. Have fun. Enjoy the game." - Michael Jordan "Just play. Have fun. Enjoy the game." - Michael Jordan