Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Dec 2004 14:32:48 -0500
From:      Jung-uk Kim <jkim@niksun.com>
To:        freebsd-amd64@freebsd.org
Subject:   Re: ports/emulators/linux_base on amd64
Message-ID:  <200412271432.48988.jkim@niksun.com>
In-Reply-To: <20041215102625.GM25967@ip.net.ua>
References:  <20041214182153.GA80721@ip.net.ua> <1103066141.2041.4.camel@server.mcneil.com> <20041215102625.GM25967@ip.net.ua>

next in thread | previous in thread | raw e-mail | index | archive | help

--Boundary-00=_gNG0BOrY9Rv3wKf
Content-Type: text/plain;
  charset="euc-kr"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Wednesday 15 December 2004 05:26 am, Ruslan Ermilov wrote:
> On Tue, Dec 14, 2004 at 03:15:41PM -0800, Sean McNeil wrote:
> > On Tue, 2004-12-14 at 14:13 -0800, Sean McNeil wrote:
> > > On Tue, 2004-12-14 at 23:54 +0200, Ruslan Ermilov wrote:
> > > > On Tue, Dec 14, 2004 at 10:34:06AM -0800, Sean McNeil wrote:
> > > > [...]
> > > >
> > > > > rpm scripts should also be fixed.  It seems like a bug in
> > > > > the rpm port that no one has addressed.
> > > >
> > > > rpm port is not guilty -- running the postinstall script
> > > > manually on amd64 returns 1, but on i386 it returns 0:
> > > >
> > > > Script started on Tue Dec 14 23:10:31 2004
> > > > hammer#	/compat/linux/bin/sh
> > > > sh-2.04# uname -srm
> > > > Linux 2.4.2 amd64
> > > > sh-2.04# /usr/sbin/glibc_post_upgrade
> > > > sh-2.04# echo $?
> > > > 1
> > > > Script done on Tue Dec 14 23:10:53 2004
> > >
> > > Yes, I just got to this point.  Thanks for the confirmation. 
> > > I'm trying to find sources to glibc_post_upgrade to take a
> > > look.
> >
> > Here is what I have so far....
> >
> > The source looks like this:
> >
> > #ifdef ARCH_386
> >   /* Work around rpm bug */
> >   char *remove_file[] = {
> >     "/lib/i686/libc-" VERSION ".so",
> >     "/lib/i686/libm-" VERSION ".so",
> >     "/lib/i686/libpthread-" PVERSION ".so",
> >     "/lib/i686/libc.so.6",
> >     "/lib/i686/libm.so.6",
> >     "/lib/i686/libpthread.so.0",
> >     NULL };
> >   int i;
> >
> >   for (i = 0; remove_file[i]; i++)
> >     unlink (remove_file[i]);
> > #endif
> >   pid = vfork ();
> >   if (pid == 0) {
> >     execl ("/sbin/ldconfig", "/sbin/ldconfig", NULL);
> >     _exit (1);
> >   } else if (pid < 0) {
> >     _exit (1);
> >   }
> >   if (waitpid (0, &status, 0) != pid || !WIFEXITED (status)) {
> >     _exit (1);
> >   }
> >   if (WEXITSTATUS (status))
> >     _exit (WEXITSTATUS (status));
> >
> > ktrace shows:
> >
> >   2018 ktrace   RET   ktrace 0
> >   2018 ktrace   CALL
> > execve(0x7fffffffee0f,0x7fffffffec60,0x7fffffffec70)
> >   2018 ktrace   NAMI  "/compat/linux/usr/sbin/glibc_post_upgrade"
> >   2018 glibc_post_upgrade RET   execve 0
> >   2018 glibc_post_upgrade CALL  unlink(0x8048788)
> >   2018 glibc_post_upgrade NAMI 
> > "/compat/linux/lib/i686/libc-2.2.4.so" 2018 glibc_post_upgrade
> > NAMI  "/lib/i686/libc-2.2.4.so" 2018 glibc_post_upgrade RET  
> > unlink JUSTRETURN
> >   2018 glibc_post_upgrade CALL  unlink(0x80487a0)
> >   2018 glibc_post_upgrade NAMI 
> > "/compat/linux/lib/i686/libm-2.2.4.so" 2018 glibc_post_upgrade
> > NAMI  "/lib/i686/libm-2.2.4.so" 2018 glibc_post_upgrade RET  
> > unlink JUSTRETURN
> >   2018 glibc_post_upgrade CALL  unlink(0x80487b8)
> >   2018 glibc_post_upgrade NAMI
> > "/compat/linux/lib/i686/libpthread-0.9.so"
> >   2018 glibc_post_upgrade NAMI  "/lib/i686/libpthread-0.9.so"
> >   2018 glibc_post_upgrade RET   unlink JUSTRETURN
> >   2018 glibc_post_upgrade CALL  unlink(0x80487d4)
> >   2018 glibc_post_upgrade NAMI 
> > "/compat/linux/lib/i686/libc.so.6" 2018 glibc_post_upgrade NAMI 
> > "/lib/i686/libc.so.6"
> >   2018 glibc_post_upgrade RET   unlink JUSTRETURN
> >   2018 glibc_post_upgrade CALL  unlink(0x80487e8)
> >   2018 glibc_post_upgrade NAMI 
> > "/compat/linux/lib/i686/libm.so.6" 2018 glibc_post_upgrade NAMI 
> > "/lib/i686/libm.so.6"
> >   2018 glibc_post_upgrade RET   unlink JUSTRETURN
> >   2018 glibc_post_upgrade CALL  unlink(0x80487fc)
> >   2018 glibc_post_upgrade NAMI 
> > "/compat/linux/lib/i686/libpthread.so.0" 2018 glibc_post_upgrade
> > NAMI  "/lib/i686/libpthread.so.0" 2018 glibc_post_upgrade RET  
> > unlink JUSTRETURN
> >   2018 glibc_post_upgrade CALL  lstat
> >   2018 glibc_post_upgrade RET   lstat 2019/0x7e3
> >   2018 glibc_post_upgrade CALL  old.sendmsg(0,0xffffdb8c,0,0)
> >   2018 glibc_post_upgrade RET   old.sendmsg 2019/0x7e3
> >   2018 glibc_post_upgrade CALL  exit(0x1)
> >
> > Looks like there is a mismatch in kernel entry points here.
> >
> > lstat instead of vfork and old.sendmsg instead of (maybe)
> > waitpid.
> >
> > Does ktrace work with linux abi?
>
> On i386 it looks identical, except that sendmsg doesn't result in
> exit(0x1):
>
>  20167 ktrace   RET   ktrace 0
>  20167 ktrace   CALL  execve(0xbfbfec77,0xbfbfeb60,0xbfbfeb68)
>  20167 ktrace   NAMI  "/compat/linux/usr/sbin/glibc_post_upgrade"
>  20167 glibc_post_upgrade RET   execve 0
>  20167 glibc_post_upgrade CALL  unlink(0x8048788)
>  20167 glibc_post_upgrade NAMI 
> "/compat/linux/lib/i686/libc-2.2.4.so" 20167 glibc_post_upgrade
> NAMI  "/lib/i686/libc-2.2.4.so"
>  20167 glibc_post_upgrade RET   unlink JUSTRETURN
>  20167 glibc_post_upgrade CALL  unlink(0x80487a0)
>  20167 glibc_post_upgrade NAMI 
> "/compat/linux/lib/i686/libm-2.2.4.so" 20167 glibc_post_upgrade
> NAMI  "/lib/i686/libm-2.2.4.so"
>  20167 glibc_post_upgrade RET   unlink JUSTRETURN
>  20167 glibc_post_upgrade CALL  unlink(0x80487b8)
>  20167 glibc_post_upgrade NAMI 
> "/compat/linux/lib/i686/libpthread-0.9.so" 20167 glibc_post_upgrade
> NAMI  "/lib/i686/libpthread-0.9.so" 20167 glibc_post_upgrade RET  
> unlink JUSTRETURN
>  20167 glibc_post_upgrade CALL  unlink(0x80487d4)
>  20167 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libc.so.6"
>  20167 glibc_post_upgrade NAMI  "/lib/i686/libc.so.6"
>  20167 glibc_post_upgrade RET   unlink JUSTRETURN
>  20167 glibc_post_upgrade CALL  unlink(0x80487e8)
>  20167 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libm.so.6"
>  20167 glibc_post_upgrade NAMI  "/lib/i686/libm.so.6"
>  20167 glibc_post_upgrade RET   unlink JUSTRETURN
>  20167 glibc_post_upgrade CALL  unlink(0x80487fc)
>  20167 glibc_post_upgrade NAMI 
> "/compat/linux/lib/i686/libpthread.so.0" 20167 glibc_post_upgrade
> NAMI  "/lib/i686/libpthread.so.0" 20167 glibc_post_upgrade RET  
> unlink JUSTRETURN
>  20167 glibc_post_upgrade CALL  lstat
>  20167 glibc_post_upgrade RET   lstat 20168/0x4ec8
>  20167 glibc_post_upgrade CALL  old.sendmsg(0,0xbfbfea1c,0,0)
>  20167 glibc_post_upgrade RET   old.sendmsg 20168/0x4ec8
>  20167 glibc_post_upgrade CALL  accept(0x8048880,0)
>  20167 glibc_post_upgrade NAMI 
> "/compat/linux/usr/lib/gconv/gconv-modules.cache" 20167
> glibc_post_upgrade NAMI  "/compat/linux"
>  20167 glibc_post_upgrade NAMI 
> "/compat/linux/usr/lib/gconv/gconv-modules.cache" 20167
> glibc_post_upgrade RET   accept 0
>  20167 glibc_post_upgrade CALL  lstat
>  20167 glibc_post_upgrade RET   lstat 20171/0x4ecb
>  20167 glibc_post_upgrade CALL  old.sendmsg(0,0xbfbfea1c,0,0)
>  20167 glibc_post_upgrade RET   old.sendmsg 20171/0x4ecb
>  20167 glibc_post_upgrade CALL  access(0x804883b,0x1)
>  20167 glibc_post_upgrade NAMI  "/compat/linux/sbin/telinit"
>  20167 glibc_post_upgrade NAMI  "/sbin/telinit"
>  20167 glibc_post_upgrade RET   access JUSTRETURN
>  20167 glibc_post_upgrade CALL  exit(0)
>
> The reason for this is as follows:
>
> hammer# grep -C3 TJR /sys/compat/linux/linux_socket.c
>         struct iovec *iov;
>         int error;
>
>         /* XXXTJR sendmsg is broken on amd64 */
>
>         error = copyin(args, &linux_args, sizeof(linux_args));
>         if (error)
> --
>         struct cmsghdr *cmsg;
>         int error;
>
>         /* XXXTJR recvmsg is broken on amd64 */
>
>         if ((error = copyin(args, &linux_args,
> sizeof(linux_args)))) return (error);

I thought sendmsg was the culprit too but it wasn't.  You guys
forgot '-i' option for krace (to trace children).  The problem
is in linux_execve() from src/sys/amd64/linux32/linux32_machdep.c.

   888 glibc_post_upgrade RET   fork 0
   888 glibc_post_upgrade CALL  obs_execv(0x80490ee,0xffffb644,0)
   888 glibc_post_upgrade NAMI  "/compat/linux/sbin/ldconfig"
   888 glibc_post_upgrade NAMI  "/compat/linux"
   888 glibc_post_upgrade NAMI  "/compat/linux/sbin/ldconfig"
   888 glibc_post_upgrade RET   obs_execv -1 errno -14 Unknown error: -14
   888 glibc_post_upgrade CALL  exit(0x6e)

One of copyin/copyout is failing from linux_execve() with EFAULT.
On i386, it returns 0, of course.  Parent exited because child
failed.  Full ktrace dump and glibc_post_upgrade.c (with RedHat
8.0's local patch) attached.

Thanks,

Jung-uk Kim

--Boundary-00=_gNG0BOrY9Rv3wKf
Content-Type: text/plain;
  charset="euc-kr";
  name="glibc_post_upgrade.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="glibc_post_upgrade.c"

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include <dirent.h>
#include <stddef.h>
#include <fcntl.h>
#include <string.h>

int main(void)
{
  pid_t pid;
  int status;
  char initpath[256];

#ifdef ARCH_386
  char buffer[4096];
  char *remove_file[] = {
    "/lib/i686/libc-" VERSION ".so",
    "/lib/i686/libm-" VERSION ".so",
    "/lib/i686/librt-" VERSION ".so",
    "/lib/i686/libpthread-" PVERSION ".so",
    "/lib/i686/libc.so.6",
    "/lib/i686/libm.so.6",
    "/lib/i686/librt.so.1",
    "/lib/i686/libpthread.so.0",
    NULL };
  struct pref {
    char *p;
    int len;
  } prefix[] = { { "libc-", 5 }, { "libm-", 5 },
		 { "librt-", 6 }, { "libpthread-", 11 } };
  int i, fd;
  off_t base;
  ssize_t ret;

  for (i = 0; remove_file[i]; i++)
    unlink (remove_file[i]);
  fd = open ("/lib/i686", O_RDONLY);
  if (fd >= 0
      && (ret = getdirentries (fd, buffer, sizeof (buffer), &base))
	>= (ssize_t) offsetof (struct dirent, d_name))
    {
      for (base = 0; base + offsetof (struct dirent, d_name) < ret; )
       {
	 struct dirent *d = (struct dirent *) (buffer + base);

	 for (i = 0; i < sizeof (prefix) / sizeof (prefix[0]); i++)
	   if (! strncmp (d->d_name, prefix[i].p, prefix[i].len))
	     {
	       char *p = d->d_name + prefix[i].len;

	       while (*p == '.' || (*p >= '0' && *p <= '9')) p++;
	       if (p[0] == 's' && p[1] == 'o' && p[2] == '\0'
		   && p + 3 - d->d_name < sizeof (initpath) - strlen ("/lib/i686/"))
		 {
		   strcpy (initpath, "/lib/i686/");
		   strcpy (initpath + strlen ("/lib/i686/"), d->d_name);
		   unlink (initpath);
		   break;
		 }
	     }
	 base += d->d_reclen;
       }
      close (fd);
    }
#endif

  pid = vfork ();
  if (pid == 0)
    {
      execl ("/sbin/ldconfig", "/sbin/ldconfig", NULL);
      _exit (110);
    }
  else if (pid < 0)
    _exit (111);
  if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
    _exit (112);
  if (WEXITSTATUS (status))
    _exit (WEXITSTATUS (status));

  if (! utimes (GCONV_MODULES_CACHE, NULL))
    {
      pid = vfork ();
      if (pid == 0)
	{
	  execl ("/usr/sbin/iconvconfig", "/usr/sbin/iconvconfig", NULL);
	  _exit (113);
	}
      else if (pid < 0)
	_exit (114);
      if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
	_exit (115);
      if (WEXITSTATUS (status))
	_exit (WEXITSTATUS (status));
    }

  /* Check if telinit is available and the init fifo as well.  */
  if (access ("/sbin/telinit", X_OK) || access ("/dev/initctl", F_OK))
    _exit (0);
  /* Check if we are not inside of some chroot, because we'd just
     timeout and leave /etc/initrunlvl.  */
  if (readlink ("/proc/1/exe", initpath, 256) <= 0 ||
      readlink ("/proc/1/root", initpath, 256) <= 0)
    _exit (0);

  pid = vfork ();
  if (pid == 0)
    {
      execl ("/sbin/telinit", "/sbin/telinit", "u", NULL);
      _exit (116);
    }
  else if (pid < 0)
    _exit (117);
  if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
    _exit (118);

  /* Check if we can safely condrestart sshd.  */
  if (access ("/sbin/service", X_OK) == 0
      && access ("/usr/sbin/sshd", X_OK) == 0
      && access ("/bin/bash", X_OK) == 0)
    {
      pid = vfork ();
      if (pid == 0)
	{
	  execl ("/sbin/service", "/sbin/service", "sshd", "condrestart", NULL);
	  _exit (119);
	}
      else if (pid < 0)
	_exit (120);
      if (waitpid (0, &status, 0) != pid || !WIFEXITED (status))
	_exit (121);
    }

  _exit(0);
}

int __libc_multiple_threads;
int __libc_enable_asynccancel (void) { return 0; }
void __libc_disable_asynccancel (int x) { }
void __libc_csu_init (void) { }
void __libc_csu_fini (void) { }
pid_t __fork (void) { return -1; }
char thr_buf[8192];

#ifndef __powerpc__
int __libc_start_main (int (*main) (void), int argc, char **argv,
		       void (*init) (void), void (*fini) (void),
		       void (*rtld_fini) (void), void * stack_end)
#else
struct startup_info
{
  void *sda_base;
  int (*main) (int, char **, char **, void *);
  int (*init) (int, char **, char **, void *);
  void (*fini) (void);
};

int __libc_start_main (int argc, char **ubp_av,
		       char **ubp_ev,
		       void *auxvec, void (*rtld_fini) (void),
		       struct startup_info *stinfo,
		       char **stack_on_entry)
#endif
{
#if defined __ia64__ || defined __powerpc64__
  register void *r13 __asm ("r13") = thr_buf + 4096;
  __asm ("" : : "r" (r13));
#elif defined __sparc__
  register void *g6 __asm ("g6") = thr_buf + 4096;
  register void *g7 __asm ("g7") = thr_buf + 4096;
  __asm ("" : : "r" (g6), "r" (g7));
#elif defined __s390__ && !defined __s390x__
  __asm ("sar %%a0,%0" : : "d" (thr_buf + 4096));
#elif defined __s390x__
  __asm ("sar %%a1,%0; srlg 0,%0,32; sar %%a0,0" : : "d" (thr_buf + 4096) : "0");
#elif defined __powerpc__ && !defined __powerpc64__
  register void *r2 __asm ("r2") = thr_buf + 4096;
  __asm ("" : : "r" (r2));
#endif
  main();
  return 0;
}

--Boundary-00=_gNG0BOrY9Rv3wKf
Content-Type: text/plain;
  charset="euc-kr";
  name="linux32_dump.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
	filename="linux32_dump.txt"

   887 ktrace   RET   ktrace 0
   887 ktrace   CALL  execve(0x7fffffffe963,0x7fffffffe750,0x7fffffffe760)
   887 ktrace   NAMI  "/usr/compat/linux/usr/sbin/glibc_post_upgrade"
   887 glibc_post_upgrade RET   execve 0
   887 glibc_post_upgrade CALL  unlink(0x8049008)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libc-2.3.2.so"
   887 glibc_post_upgrade NAMI  "/lib/i686/libc-2.3.2.so"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  unlink(0x8049020)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libm-2.3.2.so"
   887 glibc_post_upgrade NAMI  "/lib/i686/libm-2.3.2.so"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  unlink(0x8049038)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/librt-2.3.2.so"
   887 glibc_post_upgrade NAMI  "/lib/i686/librt-2.3.2.so"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  unlink(0x8049051)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libpthread-0.10.so"
   887 glibc_post_upgrade NAMI  "/lib/i686/libpthread-0.10.so"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  unlink(0x804906e)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libc.so.6"
   887 glibc_post_upgrade NAMI  "/lib/i686/libc.so.6"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  unlink(0x8049082)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libm.so.6"
   887 glibc_post_upgrade NAMI  "/lib/i686/libm.so.6"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  unlink(0x8049096)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/librt.so.1"
   887 glibc_post_upgrade NAMI  "/lib/i686/librt.so.1"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  unlink(0x80490ab)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686/libpthread.so.0"
   887 glibc_post_upgrade NAMI  "/lib/i686/libpthread.so.0"
   887 glibc_post_upgrade RET   unlink JUSTRETURN
   887 glibc_post_upgrade CALL  open(0x80490e4,0,0)
   887 glibc_post_upgrade NAMI  "/compat/linux/lib/i686"
   887 glibc_post_upgrade NAMI  "/lib/i686"
   887 glibc_post_upgrade RET   open JUSTRETURN
   887 glibc_post_upgrade CALL  lstat
   888 glibc_post_upgrade RET   fork 0
   888 glibc_post_upgrade CALL  obs_execv(0x80490ee,0xffffb644,0)
   888 glibc_post_upgrade NAMI  "/compat/linux/sbin/ldconfig"
   888 glibc_post_upgrade NAMI  "/compat/linux"
   888 glibc_post_upgrade NAMI  "/compat/linux/sbin/ldconfig"
   888 glibc_post_upgrade RET   obs_execv -1 errno -14 Unknown error: -14
   888 glibc_post_upgrade CALL  exit(0x6e)
   887 glibc_post_upgrade RET   lstat 888/0x378
   887 glibc_post_upgrade CALL  old.sendmsg(0,0xffffc68c,0,0)
   887 glibc_post_upgrade RET   old.sendmsg 888/0x378
   887 glibc_post_upgrade CALL  exit(0x6e)

--Boundary-00=_gNG0BOrY9Rv3wKf--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200412271432.48988.jkim>