Print this page
    
OS-4119 lxbrand panic when running native perl inside lx zone
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/exec/aout/aout.c
          +++ new/usr/src/uts/common/exec/aout/aout.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
       25 + * Copyright 2015, Joyent, Inc.
  25   26   */
  26   27  
  27   28  #include <sys/types.h>
  28   29  #include <sys/param.h>
  29   30  #include <sys/systm.h>
  30   31  #include <sys/fpu/fpusystm.h>
  31   32  #include <sys/sysmacros.h>
  32   33  #include <sys/signal.h>
  33   34  #include <sys/cred.h>
  34   35  #include <sys/user.h>
  35   36  #include <sys/errno.h>
  36   37  #include <sys/vnode.h>
  37   38  #include <sys/mman.h>
  38   39  #include <sys/kmem.h>
  39   40  #include <sys/proc.h>
  40   41  #include <sys/pathname.h>
  41   42  #include <sys/cmn_err.h>
  42   43  #include <sys/debug.h>
  43   44  #include <sys/exec.h>
  44   45  #include <sys/exechdr.h>
  45   46  #include <sys/auxv.h>
  46   47  #include <sys/core.h>
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  47   48  #include <sys/vmparam.h>
  48   49  #include <sys/archsystm.h>
  49   50  #include <sys/fs/swapnode.h>
  50   51  #include <sys/modctl.h>
  51   52  #include <vm/anon.h>
  52   53  #include <vm/as.h>
  53   54  #include <vm/seg.h>
  54   55  
  55   56  static int aoutexec(vnode_t *vp, execa_t *uap, uarg_t *args,
  56   57      intpdata_t *idatap, int level, long *execsz, int setid,
  57      -    caddr_t exec_file, cred_t *cred, int brand_action);
       58 +    caddr_t exec_file, cred_t *cred, int *brand_action);
  58   59  static int get_aout_head(struct vnode **vpp, struct exdata *edp, long *execsz,
  59   60      int *isdyn);
  60   61  static int aoutcore(vnode_t *vp, proc_t *pp, cred_t *credp,
  61   62      rlim64_t rlimit, int sig, core_content_t content);
  62   63  extern int elf32exec(vnode_t *, execa_t *, uarg_t *, intpdata_t *, int,
  63   64      long *, int, caddr_t, cred_t *, int);
  64   65  extern int elf32core(vnode_t *, proc_t *, cred_t *, rlim64_t, int,
  65   66      core_content_t);
  66   67  
  67   68  static struct execsw nesw = {
  68   69          aout_nmagicstr,
  69   70          2,
  70   71          2,
  71   72          aoutexec,
  72   73          aoutcore
  73   74  };
  74   75  
  75   76  static struct execsw zesw = {
  76   77          aout_zmagicstr,
  77   78          2,
  78   79          2,
  79   80          aoutexec,
  80   81          aoutcore
  81   82  };
  82   83  
  83   84  static struct execsw oesw = {
  84   85          aout_omagicstr,
  85   86          2,
  86   87          2,
  87   88          aoutexec,
  88   89          aoutcore
  89   90  };
  90   91  
  91   92  /*
  92   93   * Module linkage information for the kernel.
  93   94   */
  94   95  static struct modlexec nexec = {
  95   96          &mod_execops, "exec for NMAGIC", &nesw
  96   97  };
  97   98  
  98   99  static struct modlexec zexec = {
  99  100          &mod_execops, "exec for ZMAGIC", &zesw
 100  101  };
 101  102  
 102  103  static struct modlexec oexec = {
 103  104          &mod_execops, "exec for OMAGIC", &oesw
 104  105  };
 105  106  
 106  107  static struct modlinkage modlinkage = {
 107  108          MODREV_1, &nexec, &zexec, &oexec, NULL
 108  109  };
 109  110  
 110  111  int
 111  112  _init(void)
 112  113  {
 113  114          return (mod_install(&modlinkage));
 114  115  }
 115  116  
 116  117  int
 117  118  _fini(void)
 118  119  {
 119  120          return (mod_remove(&modlinkage));
 120  121  }
 121  122  
 122  123  int
  
    | 
      ↓ open down ↓ | 
    55 lines elided | 
    
      ↑ open up ↑ | 
  
 123  124  _info(struct modinfo *modinfop)
 124  125  {
 125  126          return (mod_info(&modlinkage, modinfop));
 126  127  }
 127  128  
 128  129  
 129  130  /*ARGSUSED*/
 130  131  static int
 131  132  aoutexec(vnode_t *vp, struct execa *uap, struct uarg *args,
 132  133      struct intpdata *idatap, int level, long *execsz, int setid,
 133      -    caddr_t exec_file, cred_t *cred, int brand_action)
      134 +    caddr_t exec_file, cred_t *cred, int *brand_action)
 134  135  {
 135  136          auxv32_t auxflags_auxv32;
 136  137          int error;
 137  138          struct exdata edp, edpout;
 138  139          struct execenv exenv;
 139  140          proc_t *pp = ttoproc(curthread);
 140  141          struct vnode *nvp;
 141  142          int pagetext, pagedata;
 142  143          int dataprot = PROT_ALL;
 143  144          int textprot = PROT_ALL & ~PROT_WRITE;
 144  145          int isdyn;
 145  146  
 146  147  
 147  148          args->to_model = DATAMODEL_ILP32;
 148  149          *execsz = btopr(SINCR) + btopr(SSIZE) + btopr(NCARGS32-1);
 149  150  
 150  151          /*
 151  152           * Read in and validate the file header.
 152  153           */
 153  154          if (error = get_aout_head(&vp, &edp, execsz, &isdyn))
 154  155                  return (error);
 155  156  
 156  157          if (error = chkaout(&edp))
 157  158                  return (error);
 158  159  
 159  160          /*
 160  161           * Take a quick look to see if it looks like we will have
 161  162           * enough swap space for the program to get started.  This
 162  163           * is not a guarantee that we will succeed, but it is definitely
 163  164           * better than finding this out after we are committed to the
 164  165           * new memory image.  Maybe what is needed is a way to "prereserve"
 165  166           * swap space for some segment mappings here.
 166  167           *
 167  168           * But with shared libraries the process can make it through
 168  169           * the exec only to have ld.so fail to get the program going
 169  170           * because its mmap's will not be able to succeed if the system
 170  171           * is running low on swap space.  In fact this is a far more
 171  172           * common failure mode, but we cannot do much about this here
 172  173           * other than add some slop to our anonymous memory resources
 173  174           * requirements estimate based on some guess since we cannot know
 174  175           * what else the program will really need to get to a useful state.
 175  176           *
 176  177           * XXX - The stack size (clrnd(SSIZE + btopr(nargc))) should also
 177  178           * be used when checking for swap space.  This requires some work
 178  179           * since nargc is actually determined in exec_args() which is done
 179  180           * after this check and hence we punt for now.
 180  181           *
 181  182           * nargc = SA(nc + (na + 4) * NBPW) + sizeof (struct rwindow);
 182  183           */
 183  184          if (CURRENT_TOTAL_AVAILABLE_SWAP < btopr(edp.ux_dsize) + btopr(SSIZE))
 184  185                  return (ENOMEM);
 185  186  
 186  187          /*
 187  188           * Load the trap 0 interpreter.
 188  189           */
 189  190          if (error = lookupname("/usr/4lib/sbcp", UIO_SYSSPACE, FOLLOW,
 190  191              NULLVPP, &nvp)) {
 191  192                  goto done;
 192  193          }
 193  194          if (error = elf32exec(nvp, uap, args, idatap, level, execsz,
 194  195              setid, exec_file, cred, brand_action)) {
 195  196                  VN_RELE(nvp);
 196  197                  return (error);
 197  198          }
 198  199          VN_RELE(nvp);
 199  200  
 200  201          /*
 201  202           * Determine the a.out's characteristics.
 202  203           */
 203  204          getexinfo(&edp, &edpout, &pagetext, &pagedata);
 204  205  
 205  206          /*
 206  207           * Load the a.out's text and data.
 207  208           */
 208  209          if (error = execmap(edp.vp, edp.ux_txtorg, edp.ux_tsize,
 209  210              (size_t)0, edp.ux_toffset, textprot, pagetext, 0))
 210  211                  goto done;
 211  212          if (error = execmap(edp.vp, edp.ux_datorg, edp.ux_dsize,
 212  213              edp.ux_bsize, edp.ux_doffset, dataprot, pagedata, 0))
 213  214                  goto done;
 214  215  
 215  216          exenv.ex_bssbase = (caddr_t)edp.ux_datorg;
 216  217          exenv.ex_brkbase = (caddr_t)edp.ux_datorg;
 217  218          exenv.ex_brksize = edp.ux_dsize + edp.ux_bsize;
 218  219          exenv.ex_magic = edp.ux_mag;
 219  220          exenv.ex_vp = edp.vp;
 220  221          setexecenv(&exenv);
 221  222  
 222  223          /*
 223  224           * It's time to manipulate the process aux vectors.
 224  225           * We need to update the AT_SUN_AUXFLAGS aux vector to set
 225  226           * the AF_SUN_NOPLM flag.
 226  227           */
 227  228          if (copyin(args->auxp_auxflags, &auxflags_auxv32,
 228  229              sizeof (auxflags_auxv32)) != 0)
 229  230                  return (EFAULT);
 230  231  
 231  232          ASSERT(auxflags_auxv32.a_type == AT_SUN_AUXFLAGS);
 232  233          auxflags_auxv32.a_un.a_val |= AF_SUN_NOPLM;
 233  234          if (copyout(&auxflags_auxv32, args->auxp_auxflags,
 234  235              sizeof (auxflags_auxv32)) != 0)
 235  236                  return (EFAULT);
 236  237  
 237  238  done:
 238  239          if (error != 0)
 239  240                  psignal(pp, SIGKILL);
 240  241          else {
 241  242                  /*
 242  243                   * Ensure that the max fds do not exceed 256 (this is
 243  244                   * applicable to 4.x binaries, which is why we only
 244  245                   * do it on a.out files).
 245  246                   */
 246  247                  struct rlimit64 fdno_rlim;
 247  248                  rctl_alloc_gp_t *gp = rctl_rlimit_set_prealloc(1);
 248  249  
 249  250                  mutex_enter(&curproc->p_lock);
 250  251                  (void) rctl_rlimit_get(rctlproc_legacy[RLIMIT_NOFILE], curproc,
 251  252                      &fdno_rlim);
 252  253                  if (fdno_rlim.rlim_cur > 256) {
 253  254                          fdno_rlim.rlim_cur = fdno_rlim.rlim_max = 256;
 254  255                          (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE],
 255  256                              curproc, &fdno_rlim, gp,
 256  257                              rctlproc_flags[RLIMIT_NOFILE],
 257  258                              rctlproc_signals[RLIMIT_NOFILE], CRED());
 258  259                  } else if (fdno_rlim.rlim_max > 256) {
 259  260                          fdno_rlim.rlim_max = 256;
 260  261                          (void) rctl_rlimit_set(rctlproc_legacy[RLIMIT_NOFILE],
 261  262                              curproc, &fdno_rlim, gp,
 262  263                              rctlproc_flags[RLIMIT_NOFILE],
 263  264                              rctlproc_signals[RLIMIT_NOFILE], CRED());
 264  265                  }
 265  266                  mutex_exit(&curproc->p_lock);
 266  267  
 267  268                  rctl_prealloc_destroy(gp);
 268  269          }
 269  270  
 270  271          return (error);
 271  272  }
 272  273  
 273  274  /*
 274  275   * Read in and validate the file header.
 275  276   */
 276  277  static int
 277  278  get_aout_head(struct vnode **vpp, struct exdata *edp, long *execsz, int *isdyn)
 278  279  {
 279  280          struct vnode *vp = *vpp;
 280  281          struct exec filhdr;
 281  282          int error;
 282  283          ssize_t resid;
 283  284          rlim64_t limit;
 284  285          rlim64_t roundlimit;
 285  286  
 286  287          if (error = vn_rdwr(UIO_READ, vp, (caddr_t)&filhdr,
 287  288              (ssize_t)sizeof (filhdr), (offset_t)0, UIO_SYSSPACE, 0,
 288  289              (rlim64_t)0, CRED(), &resid))
 289  290                  return (error);
 290  291  
 291  292          if (resid != 0)
 292  293                  return (ENOEXEC);
 293  294  
 294  295          switch (filhdr.a_magic) {
 295  296          case OMAGIC:
 296  297                  filhdr.a_data += filhdr.a_text;
 297  298                  filhdr.a_text = 0;
 298  299                  break;
 299  300          case ZMAGIC:
 300  301          case NMAGIC:
 301  302                  break;
 302  303          default:
 303  304                  return (ENOEXEC);
 304  305          }
 305  306  
 306  307          /*
 307  308           * Check total memory requirements (in pages) for a new process
 308  309           * against the available memory or upper limit of memory allowed.
 309  310           *
 310  311           * For the 64-bit kernel, the limit can be set large enough so that
 311  312           * rounding it up to a page can overflow, so we check for btopr()
 312  313           * overflowing here by comparing it with the unrounded limit in pages.
 313  314           */
 314  315          *execsz += btopr(filhdr.a_text + filhdr.a_data);
 315  316          limit = btop(curproc->p_vmem_ctl);
 316  317          roundlimit = btopr(curproc->p_vmem_ctl);
 317  318          if ((roundlimit > limit && *execsz > roundlimit) ||
 318  319              (roundlimit < limit && *execsz > limit)) {
 319  320                  mutex_enter(&curproc->p_lock);
 320  321                  (void) rctl_action(rctlproc_legacy[RLIMIT_VMEM],
 321  322                      curproc->p_rctls, curproc, RCA_SAFE);
 322  323                  mutex_exit(&curproc->p_lock);
 323  324                  return (ENOMEM);
 324  325          }
 325  326  
 326  327          edp->ux_mach = filhdr.a_machtype;
 327  328          edp->ux_tsize = filhdr.a_text;
 328  329          edp->ux_dsize = filhdr.a_data;
 329  330          edp->ux_bsize = filhdr.a_bss;
 330  331          edp->ux_mag = filhdr.a_magic;
 331  332          edp->ux_toffset = gettfile(&filhdr);
 332  333          edp->ux_doffset = getdfile(&filhdr);
 333  334          edp->ux_txtorg = gettmem(&filhdr);
 334  335          edp->ux_datorg = getdmem(&filhdr);
 335  336          edp->ux_entloc = (caddr_t)(uintptr_t)filhdr.a_entry;
 336  337          edp->vp = vp;
 337  338          *isdyn = filhdr.a_dynamic;
 338  339  
 339  340          return (0);
 340  341  }
 341  342  
 342  343  static int
 343  344  aoutcore(vnode_t *vp, proc_t *pp, struct cred *credp, rlim64_t rlimit, int sig,
 344  345      core_content_t content)
 345  346  {
 346  347          return (elf32core(vp, pp, credp, rlimit, sig, content));
 347  348  }
  
    | 
      ↓ open down ↓ | 
    204 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX