Print this page
7029 want per-process exploit mitigation features (secflags)
7030 want basic address space layout randomization (aslr)
7031 noexec_user_stack should be a secflag
7032 want a means to forbid mappings around NULL.

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/exec/elf/elf.c
          +++ new/usr/src/uts/common/exec/elf/elf.c
↓ open down ↓ 34 lines elided ↑ open up ↑
  35   35  #include <sys/sysmacros.h>
  36   36  #include <sys/signal.h>
  37   37  #include <sys/cred.h>
  38   38  #include <sys/user.h>
  39   39  #include <sys/errno.h>
  40   40  #include <sys/vnode.h>
  41   41  #include <sys/mman.h>
  42   42  #include <sys/kmem.h>
  43   43  #include <sys/proc.h>
  44   44  #include <sys/pathname.h>
       45 +#include <sys/policy.h>
  45   46  #include <sys/cmn_err.h>
  46   47  #include <sys/systm.h>
  47   48  #include <sys/elf.h>
  48   49  #include <sys/vmsystm.h>
  49   50  #include <sys/debug.h>
  50   51  #include <sys/auxv.h>
  51   52  #include <sys/exec.h>
  52   53  #include <sys/prsystm.h>
  53   54  #include <vm/as.h>
  54   55  #include <vm/rm.h>
↓ open down ↓ 3 lines elided ↑ open up ↑
  58   59  #include <sys/systeminfo.h>
  59   60  #include <sys/vmparam.h>
  60   61  #include <sys/machelf.h>
  61   62  #include <sys/shm_impl.h>
  62   63  #include <sys/archsystm.h>
  63   64  #include <sys/fasttrap.h>
  64   65  #include <sys/brand.h>
  65   66  #include "elf_impl.h"
  66   67  #include <sys/sdt.h>
  67   68  #include <sys/siginfo.h>
       69 +#include <sys/random.h>
  68   70  
  69   71  extern int at_flags;
       72 +extern volatile size_t aslr_max_brk_skew;
  70   73  
  71   74  #define ORIGIN_STR      "ORIGIN"
  72   75  #define ORIGIN_STR_SIZE 6
  73   76  
  74   77  static int getelfhead(vnode_t *, cred_t *, Ehdr *, int *, int *, int *);
  75   78  static int getelfphdr(vnode_t *, cred_t *, const Ehdr *, int, caddr_t *,
  76   79      ssize_t *);
  77   80  static int getelfshdr(vnode_t *, cred_t *, const Ehdr *, int, int, caddr_t *,
  78   81      ssize_t *, caddr_t *, ssize_t *);
  79   82  static size_t elfsize(Ehdr *, int, caddr_t, uintptr_t *);
↓ open down ↓ 75 lines elided ↑ open up ↑
 155  158           */
 156  159          if (phdrp->p_memsz < PT_SUNWDTRACE_SIZE ||
 157  160              (phdrp->p_flags & (PF_R | PF_W | PF_X)) != (PF_R | PF_W | PF_X))
 158  161                  return (-1);
 159  162  
 160  163          args->thrptr = phdrp->p_vaddr + base;
 161  164  
 162  165          return (0);
 163  166  }
 164  167  
      168 +static int
      169 +handle_secflag_dt(proc_t *p, uint_t dt, uint_t val)
      170 +{
      171 +        uint_t flag;
      172 +
      173 +        switch (dt) {
      174 +        case DT_SUNW_ASLR:
      175 +                flag = PROC_SEC_ASLR;
      176 +                break;
      177 +        default:
      178 +                return (EINVAL);
      179 +        }
      180 +
      181 +        if (val == 0) {
      182 +                if (secflag_isset(p->p_secflags.psf_lower, flag))
      183 +                        return (EPERM);
      184 +                if ((secpolicy_psecflags(CRED(), p, p) != 0) &&
      185 +                    secflag_isset(p->p_secflags.psf_inherit, flag))
      186 +                        return (EPERM);
      187 +
      188 +                secflag_clear(&p->p_secflags.psf_inherit, flag);
      189 +                secflag_clear(&p->p_secflags.psf_effective, flag);
      190 +        } else {
      191 +                if (!secflag_isset(p->p_secflags.psf_upper, flag))
      192 +                        return (EPERM);
      193 +
      194 +                if ((secpolicy_psecflags(CRED(), p, p) != 0) &&
      195 +                    !secflag_isset(p->p_secflags.psf_inherit, flag))
      196 +                        return (EPERM);
      197 +
      198 +                secflag_set(&p->p_secflags.psf_inherit, flag);
      199 +                secflag_set(&p->p_secflags.psf_effective, flag);
      200 +        }
      201 +
      202 +        return (0);
      203 +}
      204 +
 165  205  /*
 166  206   * Map in the executable pointed to by vp. Returns 0 on success.
 167  207   */
 168  208  int
 169  209  mapexec_brand(vnode_t *vp, uarg_t *args, Ehdr *ehdr, Addr *uphdr_vaddr,
 170  210      intptr_t *voffset, caddr_t exec_file, int *interp, caddr_t *bssbase,
 171  211      caddr_t *brkbase, size_t *brksize, uintptr_t *lddatap)
 172  212  {
 173  213          size_t          len;
 174  214          struct vattr    vat;
↓ open down ↓ 73 lines elided ↑ open up ↑
 248  288          caddr_t         phdrbase = NULL;
 249  289          caddr_t         bssbase = 0;
 250  290          caddr_t         brkbase = 0;
 251  291          size_t          brksize = 0;
 252  292          ssize_t         dlnsize;
 253  293          aux_entry_t     *aux;
 254  294          int             error;
 255  295          ssize_t         resid;
 256  296          int             fd = -1;
 257  297          intptr_t        voffset;
 258      -        Phdr            *dyphdr = NULL;
      298 +        Phdr            *intphdr = NULL;
      299 +        Phdr            *dynamicphdr = NULL;
 259  300          Phdr            *stphdr = NULL;
 260  301          Phdr            *uphdr = NULL;
 261  302          Phdr            *junk = NULL;
 262  303          size_t          len;
 263  304          ssize_t         phdrsize;
 264  305          int             postfixsize = 0;
 265  306          int             i, hsize;
 266  307          Phdr            *phdrp;
 267  308          Phdr            *dataphdrp = NULL;
 268  309          Phdr            *dtrphdr;
 269  310          Phdr            *capphdr = NULL;
 270  311          Cap             *cap = NULL;
 271  312          ssize_t         capsize;
      313 +        Dyn             *dyn = NULL;
 272  314          int             hasu = 0;
 273  315          int             hasauxv = 0;
 274      -        int             hasdy = 0;
      316 +        int             hasintp = 0;
 275  317          int             branded = 0;
 276  318  
 277  319          struct proc *p = ttoproc(curthread);
 278  320          struct user *up = PTOU(p);
 279  321          struct bigwad {
 280  322                  Ehdr    ehdr;
 281  323                  aux_entry_t     elfargs[__KERN_NAUXV_IMPL];
 282  324                  char            dl_name[MAXPATHLEN];
 283  325                  char            pathbuf[MAXPATHLEN];
 284  326                  struct vattr    vattr;
↓ open down ↓ 78 lines elided ↑ open up ↑
 363  405           * Determine aux size now so that stack can be built
 364  406           * in one shot (except actual copyout of aux image),
 365  407           * determine any non-default stack protections,
 366  408           * and still have this code be machine independent.
 367  409           */
 368  410          hsize = ehdrp->e_phentsize;
 369  411          phdrp = (Phdr *)phdrbase;
 370  412          for (i = nphdrs; i > 0; i--) {
 371  413                  switch (phdrp->p_type) {
 372  414                  case PT_INTERP:
 373      -                        hasauxv = hasdy = 1;
      415 +                        hasauxv = hasintp = 1;
 374  416                          break;
 375  417                  case PT_PHDR:
 376  418                          hasu = 1;
 377  419                          break;
 378  420                  case PT_SUNWSTACK:
 379  421                          args->stk_prot = PROT_USER;
 380  422                          if (phdrp->p_flags & PF_R)
 381  423                                  args->stk_prot |= PROT_READ;
 382  424                          if (phdrp->p_flags & PF_W)
 383  425                                  args->stk_prot |= PROT_WRITE;
 384  426                          if (phdrp->p_flags & PF_X)
 385  427                                  args->stk_prot |= PROT_EXEC;
 386  428                          break;
 387  429                  case PT_LOAD:
 388  430                          dataphdrp = phdrp;
 389  431                          break;
 390  432                  case PT_SUNWCAP:
 391  433                          capphdr = phdrp;
 392  434                          break;
      435 +                case PT_DYNAMIC:
      436 +                        dynamicphdr = phdrp;
      437 +                        break;
 393  438                  }
 394  439                  phdrp = (Phdr *)((caddr_t)phdrp + hsize);
 395  440          }
 396  441  
 397  442          if (ehdrp->e_type != ET_EXEC) {
 398  443                  dataphdrp = NULL;
 399  444                  hasauxv = 1;
 400  445          }
 401  446  
 402  447          /* Copy BSS permissions to args->dat_prot */
↓ open down ↓ 22 lines elided ↑ open up ↑
 425  470                   *      AT_PAGESZ
 426  471                   *      AT_SUN_AUXFLAGS
 427  472                   *      AT_SUN_HWCAP
 428  473                   *      AT_SUN_HWCAP2
 429  474                   *      AT_SUN_PLATFORM (added in stk_copyout)
 430  475                   *      AT_SUN_EXECNAME (added in stk_copyout)
 431  476                   *      AT_NULL
 432  477                   *
 433  478                   * total == 9
 434  479                   */
 435      -                if (hasdy && hasu) {
      480 +                if (hasintp && hasu) {
 436  481                          /*
 437  482                           * Has PT_INTERP & PT_PHDR - the auxvectors that
 438  483                           * will be built are:
 439  484                           *
 440  485                           *      AT_PHDR
 441  486                           *      AT_PHENT
 442  487                           *      AT_PHNUM
 443  488                           *      AT_ENTRY
 444  489                           *      AT_LDDATA
 445  490                           *
 446  491                           * total = 5
 447  492                           */
 448  493                          args->auxsize = (9 + 5) * sizeof (aux_entry_t);
 449      -                } else if (hasdy) {
      494 +                } else if (hasintp) {
 450  495                          /*
 451  496                           * Has PT_INTERP but no PT_PHDR
 452  497                           *
 453  498                           *      AT_EXECFD
 454  499                           *      AT_LDDATA
 455  500                           *
 456  501                           * total = 2
 457  502                           */
 458  503                          args->auxsize = (9 + 2) * sizeof (aux_entry_t);
 459  504                  } else {
↓ open down ↓ 12 lines elided ↑ open up ↑
 472  517  
 473  518          if ((brand_action != EBA_NATIVE) && (PROC_IS_BRANDED(p))) {
 474  519                  branded = 1;
 475  520                  /*
 476  521                   * We will be adding 4 entries to the aux vectors.  One for
 477  522                   * the the brandname and 3 for the brand specific aux vectors.
 478  523                   */
 479  524                  args->auxsize += 4 * sizeof (aux_entry_t);
 480  525          }
 481  526  
      527 +        /* If the binary has an explicit ASLR flag, it must be honoured */
      528 +        if ((dynamicphdr != NULL) &&
      529 +            (dynamicphdr->p_filesz > 0)) {
      530 +                Dyn *dp;
      531 +                off_t i = 0;
      532 +
      533 +#define DYN_STRIDE      100
      534 +                for (i = 0; i < dynamicphdr->p_filesz;
      535 +                    i += sizeof (*dyn) * DYN_STRIDE) {
      536 +                        int ndyns = (dynamicphdr->p_filesz - i) / sizeof (*dyn);
      537 +                        size_t dynsize;
      538 +
      539 +                        ndyns = MIN(DYN_STRIDE, ndyns);
      540 +                        dynsize = ndyns * sizeof (*dyn);
      541 +
      542 +                        dyn = kmem_alloc(dynsize, KM_SLEEP);
      543 +
      544 +                        if ((error = vn_rdwr(UIO_READ, vp, (caddr_t)dyn,
      545 +                            dynsize, (offset_t)(dynamicphdr->p_offset + i),
      546 +                            UIO_SYSSPACE, 0, (rlim64_t)0,
      547 +                            CRED(), &resid)) != 0) {
      548 +                                uprintf("%s: cannot read .dynamic section\n",
      549 +                                    exec_file);
      550 +                                goto out;
      551 +                        }
      552 +
      553 +                        for (dp = dyn; dp < (dyn + ndyns); dp++) {
      554 +                                if (dp->d_tag == DT_SUNW_ASLR) {
      555 +                                        if ((error = handle_secflag_dt(p,
      556 +                                            DT_SUNW_ASLR,
      557 +                                            dp->d_un.d_val)) != 0) {
      558 +                                                uprintf("%s: error setting "
      559 +                                                    "security-flag from "
      560 +                                                    "DT_SUNW_ASLR: %d\n",
      561 +                                                    exec_file, error);
      562 +                                                goto out;
      563 +                                        }
      564 +                                }
      565 +                        }
      566 +
      567 +                        kmem_free(dyn, dynsize);
      568 +                }
      569 +        }
      570 +
 482  571          /* Hardware/Software capabilities */
 483  572          if (capphdr != NULL &&
 484  573              (capsize = capphdr->p_filesz) > 0 &&
 485  574              capsize <= 16 * sizeof (*cap)) {
 486  575                  int ncaps = capsize / sizeof (*cap);
 487  576                  Cap *cp;
 488  577  
 489  578                  cap = kmem_alloc(capsize, KM_SLEEP);
 490  579                  if ((error = vn_rdwr(UIO_READ, vp, (caddr_t)cap,
 491  580                      capsize, (offset_t)capphdr->p_offset,
↓ open down ↓ 30 lines elided ↑ open up ↑
 522  611           * If this is an ET_DYN executable (shared object),
 523  612           * determine its memory size so that mapelfexec() can load it.
 524  613           */
 525  614          if (ehdrp->e_type == ET_DYN)
 526  615                  len = elfsize(ehdrp, nphdrs, phdrbase, NULL);
 527  616          else
 528  617                  len = 0;
 529  618  
 530  619          dtrphdr = NULL;
 531  620  
 532      -        if ((error = mapelfexec(vp, ehdrp, nphdrs, phdrbase, &uphdr, &dyphdr,
      621 +        if ((error = mapelfexec(vp, ehdrp, nphdrs, phdrbase, &uphdr, &intphdr,
 533  622              &stphdr, &dtrphdr, dataphdrp, &bssbase, &brkbase, &voffset, NULL,
 534  623              len, execsz, &brksize)) != 0)
 535  624                  goto bad;
 536  625  
 537      -        if (uphdr != NULL && dyphdr == NULL)
      626 +        if (uphdr != NULL && intphdr == NULL)
 538  627                  goto bad;
 539  628  
 540  629          if (dtrphdr != NULL && dtrace_safe_phdr(dtrphdr, args, voffset) != 0) {
 541  630                  uprintf("%s: Bad DTrace phdr in %s\n", exec_file, exec_file);
 542  631                  goto bad;
 543  632          }
 544  633  
 545      -        if (dyphdr != NULL) {
      634 +        if (intphdr != NULL) {
 546  635                  size_t          len;
 547  636                  uintptr_t       lddata;
 548  637                  char            *p;
 549  638                  struct vnode    *nvp;
 550  639  
 551      -                dlnsize = dyphdr->p_filesz;
      640 +                dlnsize = intphdr->p_filesz;
 552  641  
 553  642                  if (dlnsize > MAXPATHLEN || dlnsize <= 0)
 554  643                          goto bad;
 555  644  
 556  645                  /*
 557  646                   * Read in "interpreter" pathname.
 558  647                   */
 559      -                if ((error = vn_rdwr(UIO_READ, vp, dlnp, dyphdr->p_filesz,
 560      -                    (offset_t)dyphdr->p_offset, UIO_SYSSPACE, 0, (rlim64_t)0,
      648 +                if ((error = vn_rdwr(UIO_READ, vp, dlnp, intphdr->p_filesz,
      649 +                    (offset_t)intphdr->p_offset, UIO_SYSSPACE, 0, (rlim64_t)0,
 561  650                      CRED(), &resid)) != 0) {
 562  651                          uprintf("%s: Cannot obtain interpreter pathname\n",
 563  652                              exec_file);
 564  653                          goto bad;
 565  654                  }
 566  655  
 567  656                  if (resid != 0 || dlnp[dlnsize - 1] != '\0')
 568  657                          goto bad;
 569  658  
 570  659                  /*
↓ open down ↓ 197 lines elided ↑ open up ↑
 768  857  
 769  858                  /*
 770  859                   * Record the user addr of the auxflags aux vector entry
 771  860                   * since brands may optionally want to manipulate this field.
 772  861                   */
 773  862                  args->auxp_auxflags =
 774  863                      (char *)((char *)args->stackend +
 775  864                      ((char *)&aux->a_type -
 776  865                      (char *)bigwad->elfargs));
 777  866                  ADDAUX(aux, AT_SUN_AUXFLAGS, auxf);
      867 +
 778  868                  /*
 779  869                   * Hardware capability flag word (performance hints)
 780  870                   * Used for choosing faster library routines.
 781  871                   * (Potentially different between 32-bit and 64-bit ABIs)
 782  872                   */
 783  873  #if defined(_LP64)
 784  874                  if (args->to_model == DATAMODEL_NATIVE) {
 785  875                          ADDAUX(aux, AT_SUN_HWCAP, auxv_hwcap)
 786  876                          ADDAUX(aux, AT_SUN_HWCAP2, auxv_hwcap_2)
 787  877                  } else {
↓ open down ↓ 389 lines elided ↑ open up ↑
1177 1267          return (0);
1178 1268  }
1179 1269  
1180 1270  static int
1181 1271  mapelfexec(
1182 1272          vnode_t *vp,
1183 1273          Ehdr *ehdr,
1184 1274          int nphdrs,
1185 1275          caddr_t phdrbase,
1186 1276          Phdr **uphdr,
1187      -        Phdr **dyphdr,
     1277 +        Phdr **intphdr,
1188 1278          Phdr **stphdr,
1189 1279          Phdr **dtphdr,
1190 1280          Phdr *dataphdrp,
1191 1281          caddr_t *bssbase,
1192 1282          caddr_t *brkbase,
1193 1283          intptr_t *voffset,
1194 1284          intptr_t *minaddr,
1195 1285          size_t len,
1196 1286          long *execsz,
1197 1287          size_t *brksize)
↓ open down ↓ 3 lines elided ↑ open up ↑
1201 1291          caddr_t addr = NULL;
1202 1292          size_t zfodsz;
1203 1293          int ptload = 0;
1204 1294          int page;
1205 1295          off_t offset;
1206 1296          int hsize = ehdr->e_phentsize;
1207 1297          caddr_t mintmp = (caddr_t)-1;
1208 1298          extern int use_brk_lpg;
1209 1299  
1210 1300          if (ehdr->e_type == ET_DYN) {
     1301 +                secflagset_t flags = 0;
1211 1302                  /*
1212 1303                   * Obtain the virtual address of a hole in the
1213 1304                   * address space to map the "interpreter".
1214 1305                   */
1215      -                map_addr(&addr, len, (offset_t)0, 1, 0);
     1306 +                if (secflag_enabled(curproc, PROC_SEC_ASLR))
     1307 +                        flags |= _MAP_RANDOMIZE;
     1308 +
     1309 +                map_addr(&addr, len, (offset_t)0, 1, flags);
1216 1310                  if (addr == NULL)
1217 1311                          return (ENOMEM);
1218 1312                  *voffset = (intptr_t)addr;
1219 1313  
1220 1314                  /*
1221 1315                   * Calculate the minimum vaddr so it can be subtracted out.
1222 1316                   * According to the ELF specification, since PT_LOAD sections
1223 1317                   * must be sorted by increasing p_vaddr values, this is
1224 1318                   * guaranteed to be the first PT_LOAD section.
1225 1319                   */
↓ open down ↓ 6 lines elided ↑ open up ↑
1232 1326                          phdr = (Phdr *)((caddr_t)phdr + hsize);
1233 1327                  }
1234 1328  
1235 1329          } else {
1236 1330                  *voffset = 0;
1237 1331          }
1238 1332          phdr = (Phdr *)phdrbase;
1239 1333          for (i = nphdrs; i > 0; i--) {
1240 1334                  switch (phdr->p_type) {
1241 1335                  case PT_LOAD:
1242      -                        if ((*dyphdr != NULL) && (*uphdr == NULL))
     1336 +                        if ((*intphdr != NULL) && (*uphdr == NULL))
1243 1337                                  return (0);
1244 1338  
1245 1339                          ptload = 1;
1246 1340                          prot = PROT_USER;
1247 1341                          if (phdr->p_flags & PF_R)
1248 1342                                  prot |= PROT_READ;
1249 1343                          if (phdr->p_flags & PF_W)
1250 1344                                  prot |= PROT_WRITE;
1251 1345                          if (phdr->p_flags & PF_X)
1252 1346                                  prot |= PROT_EXEC;
↓ open down ↓ 34 lines elided ↑ open up ↑
1287 1381                                              curproc, addr + phdr->p_filesz +
1288 1382                                              tlen, zfodsz - tlen, 0));
1289 1383                                  }
1290 1384                          }
1291 1385  
1292 1386                          if (curproc->p_brkpageszc != 0 && phdr == dataphdrp &&
1293 1387                              (prot & PROT_WRITE)) {
1294 1388                                  uint_t  szc = curproc->p_brkpageszc;
1295 1389                                  size_t pgsz = page_get_pagesize(szc);
1296 1390                                  caddr_t ebss = addr + phdr->p_memsz;
     1391 +                                /*
     1392 +                                 * If we need extra space to keep the BSS an
     1393 +                                 * integral number of pages in size, some of
     1394 +                                 * that space may fall beyond p_brkbase, so we
     1395 +                                 * need to set p_brksize to account for it
     1396 +                                 * being (logically) part of the brk.
     1397 +                                 */
1297 1398                                  size_t extra_zfodsz;
1298 1399  
1299 1400                                  ASSERT(pgsz > PAGESIZE);
1300 1401  
1301 1402                                  extra_zfodsz = P2NPHASE((uintptr_t)ebss, pgsz);
1302 1403  
1303 1404                                  if (error = execmap(vp, addr, phdr->p_filesz,
1304 1405                                      zfodsz + extra_zfodsz, phdr->p_offset,
1305 1406                                      prot, page, szc))
1306 1407                                          goto bad;
↓ open down ↓ 12 lines elided ↑ open up ↑
1319 1420                          if (brkbase != NULL && addr >= *brkbase) {
1320 1421                                  *brkbase = addr + phdr->p_memsz;
1321 1422                          }
1322 1423  
1323 1424                          *execsz += btopr(phdr->p_memsz);
1324 1425                          break;
1325 1426  
1326 1427                  case PT_INTERP:
1327 1428                          if (ptload)
1328 1429                                  goto bad;
1329      -                        *dyphdr = phdr;
     1430 +                        *intphdr = phdr;
1330 1431                          break;
1331 1432  
1332 1433                  case PT_SHLIB:
1333 1434                          *stphdr = phdr;
1334 1435                          break;
1335 1436  
1336 1437                  case PT_PHDR:
1337 1438                          if (ptload)
1338 1439                                  goto bad;
1339 1440                          *uphdr = phdr;
↓ open down ↓ 13 lines elided ↑ open up ↑
1353 1454                          break;
1354 1455                  }
1355 1456                  phdr = (Phdr *)((caddr_t)phdr + hsize);
1356 1457          }
1357 1458  
1358 1459          if (minaddr != NULL) {
1359 1460                  ASSERT(mintmp != (caddr_t)-1);
1360 1461                  *minaddr = (intptr_t)mintmp;
1361 1462          }
1362 1463  
     1464 +        if (brkbase != NULL && secflag_enabled(curproc, PROC_SEC_ASLR)) {
     1465 +                size_t off;
     1466 +                uintptr_t base = (uintptr_t)*brkbase;
     1467 +                uintptr_t oend = base + *brksize;
     1468 +
     1469 +                ASSERT(ISP2(aslr_max_brk_skew));
     1470 +
     1471 +                (void) random_get_pseudo_bytes((uint8_t *)&off, sizeof (off));
     1472 +                base += P2PHASE(off, aslr_max_brk_skew);
     1473 +                base = P2ROUNDUP(base, PAGESIZE);
     1474 +                *brkbase = (caddr_t)base;
     1475 +                /*
     1476 +                 * Above, we set *brksize to account for the possibility we
     1477 +                 * had to grow the 'brk' in padding out the BSS to a page
     1478 +                 * boundary.
     1479 +                 *
     1480 +                 * We now need to adjust that based on where we now are
     1481 +                 * actually putting the brk.
     1482 +                 */
     1483 +                if (oend > base)
     1484 +                        *brksize = oend - base;
     1485 +                else
     1486 +                        *brksize = 0;
     1487 +        }
     1488 +
1363 1489          return (0);
1364 1490  bad:
1365 1491          if (error == 0)
1366 1492                  error = EINVAL;
1367 1493          return (error);
1368 1494  }
1369 1495  
1370 1496  int
1371 1497  elfnote(vnode_t *vp, offset_t *offsetp, int type, int descsz, void *desc,
1372 1498      rlim64_t rlimit, cred_t *credp)
↓ open down ↓ 860 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX