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