1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
  24  */
  25 
  26 /*
  27  * Implementation of all external interfaces between ld.so.1 and libc.
  28  *
  29  * This file started as a set of routines that provided synchronization and
  30  * locking operations using calls to libthread.  libthread has merged with libc
  31  * under the Unified Process Model (UPM), and things have gotten a lot simpler.
  32  * This file continues to establish and redirect various events within ld.so.1
  33  * to interfaces within libc.
  34  *
  35  * Until libc is loaded and relocated, any external interfaces are captured
  36  * locally.  Each link-map list maintains its own set of external vectors, as
  37  * each link-map list typically provides its own libc.  Although this per-link-
  38  * map list vectoring provides a degree of flexibility, there is a protocol
  39  * expected when calling various libc interfaces.
  40  *
  41  * i.   Any new alternative link-map list should call CI_THRINIT, and then call
  42  *      CI_TLS_MODADD to register any TLS for each object of that link-map list
  43  *      (this item is labeled i. as auditors can be the first objects loaded,
  44  *      and they exist on their own lik-map list).
  45  *
  46  * ii.  For the primary link-map list, CI_TLS_STATMOD must be called first to
  47  *      register any static TLS.  This routine is called regardless of there
  48  *      being any TLS, as this routine also establishes the link-map list as the
  49  *      primary list and fixes the association of uberdata).  CI_THRINIT should
  50  *      then be called.
  51  *
  52  * iii. Any objects added to an existing link-map list (primary or alternative)
  53  *      should call CI_TLS_MODADD to register any additional TLS.
  54  *
  55  * These events are established by:
  56  *
  57  * i.   Typically, libc is loaded as part of the primary dependencies of any
  58  *      link-map list (since the Unified Process Model (UPM), libc can't be
  59  *      lazily loaded).  To minimize the possibility of loading and registering
  60  *      objects, and then tearing them down (because of a relocation error),
  61  *      external vectors are established as part of load_completion().  This
  62  *      routine is called on completion of any operation that can cause objects
  63  *      to be loaded.  This point of control insures the objects have been fully
  64  *      analyzed and relocated, and moved to their controlling link-map list.
  65  *      The external vectors are established prior to any .inits being fired.
  66  *
  67  * ii.  Calls to CI_THRINIT, and CI_TLS_MODADD also occur as part of
  68  *      load_completion().  CI_THRINIT is only called once for each link-map
  69  *      control list.
  70  *
  71  * iii. Calls to CI_TLS_STATMOD, and CI_THRINIT occur for the primary link-map
  72  *      list in the final stages of setup().
  73  *
  74  * The interfaces provide by libc can be divided into two families.  The first
  75  * family consists of those interfaces that should be called from the link-map
  76  * list.  It's possible that these interfaces convey state concerning the
  77  * link-map list they are part of:
  78  *
  79  *      CI_ATEXIT
  80  *      CI TLS_MODADD
  81  *      CI_TLS_MODREM
  82  *      CI_TLS_STATMOD
  83  *      CI_THRINIT
  84  *
  85  * The second family are global in nature, that is, the link-map list from
  86  * which they are called provides no state information.  In fact, for
  87  * CI_BIND_GUARD, the calling link-map isn't even known.  The link-map can only
  88  * be deduced after ld.so.1's global lock has been obtained.  Therefore, the
  89  * following interfaces are also maintained as global:
  90  *
  91  *      CI_LCMESSAGES
  92  *      CI_BIND_GUARD
  93  *      CI_BIND_CLEAR
  94  *      CI_THR_SELF
  95  *
  96  * Note, it is possible that these global interfaces are obtained from an
  97  * alternative link-map list that gets torn down because of a processing
  98  * failure (unlikely, because the link-map list components must be analyzed
  99  * and relocated prior to load_completion(), but perhaps the tear down is still
 100  * a possibility).  Thus the global interfaces may have to be replaced.  Once
 101  * the interfaces have been obtained from the primary link-map, they can
 102  * remain fixed, as the primary link-map isn't going to go anywhere.
 103  *
 104  * The last wrinkle in the puzzle is what happens if an alternative link-map
 105  * is loaded with no libc dependency?  In this case, the alternative objects
 106  * can not call CI_THRINIT, can not be allowed to use TLS, and will not receive
 107  * any atexit processing.
 108  *
 109  * The history of these external interfaces is defined by their version:
 110  *
 111  * TI_VERSION == 1
 112  *      Under this model libthread provided rw_rwlock/rw_unlock, through which
 113  *      all rt_mutex_lock/rt_mutex_unlock calls were vectored.
 114  *      Under libc/libthread these interfaces provided _sigon/_sigoff (unlike
 115  *      lwp/libthread that provided signal blocking via bind_guard/bind_clear).
 116  *
 117  * TI_VERSION == 2
 118  *      Under this model only libthreads bind_guard/bind_clear and thr_self
 119  *      interfaces were used.  Both libthreads blocked signals under the
 120  *      bind_guard/bind_clear interfaces.   Lower level locking is derived
 121  *      from internally bound _lwp_ interfaces.  This removes recursive
 122  *      problems encountered when obtaining locking interfaces from libthread.
 123  *      The use of mutexes over reader/writer locks also enables the use of
 124  *      condition variables for controlling thread concurrency (allows access
 125  *      to objects only after their .init has completed).
 126  *
 127  * NOTE, the TI_VERSION indicated the ti_interface version number, where the
 128  * ti_interface was a large vector of functions passed to both libc (to override
 129  * the thread stub interfaces) and ld.so.1.  ld.so.1 used only a small subset of
 130  * these interfaces.
 131  *
 132  * CI_VERSION == 1
 133  *      Introduced with CI_VERSION & CI_ATEXIT
 134  *
 135  * CI_VERSION == 2 (Solaris 8 update 2).
 136  *      Added support for CI_LCMESSAGES
 137  *
 138  * CI_VERSION == 3 (Solaris 9).
 139  *      Added the following versions to the CI table:
 140  *
 141  *              CI_BIND_GUARD, CI_BIND_CLEAR, CI_THR_SELF
 142  *              CI_TLS_MODADD, CI_TLS_MOD_REMOVE, CI_TLS_STATMOD
 143  *
 144  *      This version introduced the DT_SUNW_RTLDINFO structure as a mechanism
 145  *      to handshake with ld.so.1.
 146  *
 147  * CI_VERSION == 4 (Solaris 10).
 148  *      Added the CI_THRINIT handshake as part of the libc/libthread unified
 149  *      process model.  libc now initializes the current thread pointer from
 150  *      this interface (and no longer relies on the INITFIRST flag - which
 151  *      others have started to camp out on).
 152  *
 153  * CI_VERSION == 5 (Solaris 11).
 154  *      Use of "protected" references within libc, so that symbols are
 155  *      pre-bound, and don't require ld.so.1 binding.  This implementation
 156  *      protects libc's critical regions from being vectored to auditors.
 157  *
 158  * CI_VERSION == 6 (Solaris 11).
 159  *      Added the CI_CRITICAL handshake, to allow "mem*" family to be reexposed
 160  *      as "global", and thus be redirected to auxiliary filters.
 161  *
 162  * Release summary:
 163  *
 164  *      Solaris 8       CI_ATEXIT via _ld_libc()
 165  *                      TI_* via _ld_concurrency()
 166  *
 167  *      Solaris 9       CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
 168  *                      CI_* via RTLDINFO and _ld_libc()  - new libthread
 169  *                      TI_* via _ld_concurrency()  - old libthread
 170  *
 171  *      Solaris 10      CI_ATEXIT and CI_LCMESSAGES via _ld_libc()
 172  *                      CI_* via RTLDINFO and _ld_libc()  - new libthread
 173  */
 174 
 175 #include <sys/debug.h>
 176 #include <synch.h>
 177 #include <signal.h>
 178 #include <thread.h>
 179 #include <synch.h>
 180 #include <strings.h>
 181 #include <stdio.h>
 182 #include <debug.h>
 183 #include <libc_int.h>
 184 #include "_elf.h"
 185 #include "_rtld.h"
 186 
 187 /*
 188  * This interface provides the unified process model communication between
 189  * ld.so.1 and libc.  This interface can be called a number of times:
 190  *
 191  *   -  Initially, this interface is called to process RTLDINFO.  This data
 192  *      structure is typically provided by libc, and contains the address of
 193  *      libc interfaces that must be called to initialize threads information.
 194  *
 195  *   -  _ld_libc(), this interface can also be called by libc at process
 196  *      initialization, after libc has been loaded and relocated, but before
 197  *      control has been passed to any user code (.init's or main()).  This
 198  *      call provides additional libc interface information that ld.so.1 must
 199  *      call during process execution.
 200  *
 201  *   -  _ld_libc() can also be called by libc during process execution to
 202  *      re-establish interfaces such as the locale.
 203  */
 204 static void
 205 get_lcinterface(Rt_map *lmp, Lc_interface *funcs)
 206 {
 207         int             threaded = 0, entry = 0, tag;
 208         Lm_list         *lml;
 209         Lc_desc         *lcp;
 210 
 211         if ((lmp == NULL) || (funcs == NULL))
 212                 return;
 213 
 214         /*
 215          * Once the process is active, ensure we grab a lock.
 216          */
 217         if (rtld_flags & RT_FL_APPLIC)
 218                 entry = enter(0);
 219 
 220         lml = LIST(lmp);
 221         lcp = &lml->lm_lcs[0];
 222 
 223         DBG_CALL(Dbg_util_nl(lml, DBG_NL_STD));
 224 
 225         for (tag = funcs->ci_tag; tag; tag = (++funcs)->ci_tag) {
 226                 char    *gptr;
 227                 char    *lptr = funcs->ci_un.ci_ptr;
 228 
 229                 DBG_CALL(Dbg_util_lcinterface(lmp, tag, lptr));
 230 
 231                 if (tag >= CI_MAX)
 232                         continue;
 233 
 234                 /*
 235                  * Maintain all interfaces on a per-link-map basis.  Note, for
 236                  * most interfaces, only the first interface is used for any
 237                  * link-map list.  This prevents accidents with developers who
 238                  * manage to load two different versions of libc.
 239                  */
 240                 if ((lcp[tag].lc_lmp) &&
 241                     (tag != CI_LCMESSAGES) && (tag != CI_VERSION)) {
 242                         DBG_CALL(Dbg_unused_lcinterface(lmp,
 243                             lcp[tag].lc_lmp, tag));
 244                         continue;
 245                 }
 246 
 247                 lcp[tag].lc_un.lc_ptr = lptr;
 248                 lcp[tag].lc_lmp = lmp;
 249 
 250                 gptr = glcs[tag].lc_un.lc_ptr;
 251 
 252                 /*
 253                  * Process any interfaces that must be maintained on a global
 254                  * basis.
 255                  */
 256                 switch (tag) {
 257                 case CI_ATEXIT:
 258                         break;
 259 
 260                 case CI_LCMESSAGES:
 261                         /*
 262                          * At startup, ld.so.1 can establish a locale from one
 263                          * of the locale family of environment variables (see
 264                          * ld_str_env() and readenv_user()).  During process
 265                          * execution the locale can also be changed by the user.
 266                          * This interface is called from libc should the locale
 267                          * be modified.  Presently, only one global locale is
 268                          * maintained for all link-map lists, and only objects
 269                          * on the primrary link-map may change this locale.
 270                          */
 271                         if ((lml->lm_flags & LML_FLG_BASELM) &&
 272                             ((gptr == NULL) || (strcmp(gptr, lptr) != 0))) {
 273                                 /*
 274                                  * If we've obtained a message locale (typically
 275                                  * supplied via libc's setlocale()), then
 276                                  * register the locale for use in dgettext() so
 277                                  * as to reestablish the locale for ld.so.1's
 278                                  * messages.
 279                                  */
 280                                 if (gptr) {
 281                                         free((void *)gptr);
 282                                         rtld_flags |= RT_FL_NEWLOCALE;
 283                                 }
 284                                 glcs[tag].lc_un.lc_ptr = strdup(lptr);
 285 
 286                                 /*
 287                                  * Clear any cached messages.
 288                                  */
 289                                 bzero(err_strs, sizeof (err_strs));
 290                                 nosym_str = NULL;
 291                         }
 292                         break;
 293 
 294                 case CI_BIND_GUARD:
 295                 case CI_BIND_CLEAR:
 296                 case CI_THR_SELF:
 297                 case CI_CRITICAL:
 298                         /*
 299                          * If the global vector is unset, or this is the primary
 300                          * link-map, set the global vector.
 301                          */
 302                         if ((gptr == NULL) || (lml->lm_flags & LML_FLG_BASELM))
 303                                 glcs[tag].lc_un.lc_ptr = lptr;
 304 
 305                         /* FALLTHROUGH */
 306 
 307                 case CI_TLS_MODADD:
 308                 case CI_TLS_MODREM:
 309                 case CI_TLS_STATMOD:
 310                 case CI_THRINIT:
 311                         threaded++;
 312                         break;
 313 
 314                 case CI_VERSION:
 315                         if ((rtld_flags2 & RT_FL2_RTLDSEEN) == 0) {
 316                                 Aliste  idx;
 317                                 Lm_list *lml2;
 318                                 int     version;
 319 
 320                                 rtld_flags2 |= RT_FL2_RTLDSEEN;
 321 
 322                                 version = funcs->ci_un.ci_val;
 323 #if defined(CI_V_FIVE)
 324                                 if (version >= CI_V_FIVE) {
 325                                         thr_flg_nolock = THR_FLG_NOLOCK;
 326                                         thr_flg_reenter = THR_FLG_REENTER;
 327                                 }
 328 #endif
 329                                 if (version < CI_V_FOUR)
 330                                         break;
 331 
 332                                 rtld_flags2 |= RT_FL2_UNIFPROC;
 333 
 334                                 /*
 335                                  * We might have seen an auditor which is not
 336                                  * dependent on libc.  Such an auditor's link
 337                                  * map list has LML_FLG_HOLDLOCK set.  This
 338                                  * lock needs to be dropped.  Refer to
 339                                  * audit_setup() in audit.c.
 340                                  */
 341                                 if ((rtld_flags2 & RT_FL2_HASAUDIT) == 0)
 342                                         break;
 343 
 344                                 /*
 345                                  * Yes, we did.  Take care of them.
 346                                  */
 347                                 for (APLIST_TRAVERSE(dynlm_list, idx, lml2)) {
 348                                         Rt_map *map = (Rt_map *)lml2->lm_head;
 349 
 350                                         if (FLAGS(map) & FLG_RT_AUDIT) {
 351                                                 lml2->lm_flags &=
 352                                                     ~LML_FLG_HOLDLOCK;
 353                                         }
 354                                 }
 355                         }
 356                         break;
 357 
 358                 default:
 359                         break;
 360                 }
 361         }
 362 
 363         if (threaded) {
 364                 /*
 365                  * If a version of libc gives us only a subset of the TLS
 366                  * interfaces, it's confused and we discard the whole lot.
 367                  */
 368                 if ((lcp[CI_TLS_MODADD].lc_un.lc_func &&
 369                     lcp[CI_TLS_MODREM].lc_un.lc_func &&
 370                     lcp[CI_TLS_STATMOD].lc_un.lc_func) == NULL) {
 371                         lcp[CI_TLS_MODADD].lc_un.lc_func = NULL;
 372                         lcp[CI_TLS_MODREM].lc_un.lc_func = NULL;
 373                         lcp[CI_TLS_STATMOD].lc_un.lc_func = NULL;
 374                 }
 375 
 376                 /*
 377                  * Indicate that we're now thread capable.
 378                  */
 379                 if ((lml->lm_flags & LML_FLG_RTLDLM) == 0)
 380                         rtld_flags |= RT_FL_THREADS;
 381         }
 382 
 383         if (entry)
 384                 leave(lml, 0);
 385 }
 386 
 387 /*
 388  * At this point we know we have a set of objects that have been fully analyzed
 389  * and relocated.  Prior to the next major step of running .init sections (ie.
 390  * running user code), retrieve any RTLDINFO interfaces.
 391  */
 392 int
 393 rt_get_extern(Lm_list *lml, Rt_map *lmp)
 394 {
 395         if (lml->lm_rti) {
 396                 Aliste          idx;
 397                 Rti_desc        *rti;
 398 
 399                 for (ALIST_TRAVERSE(lml->lm_rti, idx, rti))
 400                         get_lcinterface(rti->rti_lmp, rti->rti_info);
 401 
 402                 free(lml->lm_rti);
 403                 lml->lm_rti = 0;
 404         }
 405 
 406         /*
 407          * Perform some sanity checks.  If we have TLS requirements we better
 408          * have the associated external interfaces.
 409          */
 410         if (lml->lm_tls &&
 411             (lml->lm_lcs[CI_TLS_STATMOD].lc_un.lc_func == NULL)) {
 412                 eprintf(lml, ERR_FATAL, MSG_INTL(MSG_TLS_NOSUPPORT),
 413                     NAME(lmp));
 414                 return (0);
 415         }
 416         return (1);
 417 }
 418 
 419 /*
 420  * Provide an interface for libc to communicate additional interface
 421  * information.
 422  */
 423 void
 424 _ld_libc(void *ptr)
 425 {
 426         get_lcinterface(_caller(caller(), CL_EXECDEF), (Lc_interface *)ptr);
 427 }
 428 
 429 static int      bindmask = 0;
 430 
 431 int
 432 rt_bind_guard(int flags)
 433 {
 434         int     (*fptr)(int);
 435         int     bindflag;
 436 
 437         if ((fptr = glcs[CI_BIND_GUARD].lc_un.lc_func) != NULL) {
 438                 return ((*fptr)(flags));
 439         } else {
 440                 bindflag = (flags & THR_FLG_RTLD);
 441                 if ((bindflag & bindmask) == 0) {
 442                         bindmask |= bindflag;
 443                         return (1);
 444                 }
 445                 return (0);
 446         }
 447 }
 448 
 449 int
 450 rt_bind_clear(int flags)
 451 {
 452         int     (*fptr)(int);
 453         int     bindflag;
 454 
 455         if ((fptr = glcs[CI_BIND_CLEAR].lc_un.lc_func) != NULL) {
 456                 return ((*fptr)(flags));
 457         } else {
 458                 bindflag = (flags & THR_FLG_RTLD);
 459                 if (bindflag == 0)
 460                         return (bindmask);
 461                 else {
 462                         bindmask &= ~bindflag;
 463                         return (0);
 464                 }
 465         }
 466 }
 467 
 468 /*
 469  * Make sure threads have been initialized.  This interface is called once for
 470  * each link-map list.
 471  */
 472 void
 473 rt_thr_init(Lm_list *lml)
 474 {
 475         void    (*fptr)(void);
 476 
 477         if ((fptr =
 478             (void (*)())lml->lm_lcs[CI_THRINIT].lc_un.lc_func) != NULL) {
 479                 lml->lm_lcs[CI_THRINIT].lc_un.lc_func = NULL;
 480 
 481                 leave(lml, thr_flg_reenter);
 482                 (*fptr)();
 483                 (void) enter(thr_flg_reenter);
 484 
 485                 /*
 486                  * If this is an alternative link-map list, and this is the
 487                  * first call to initialize threads, don't let the destination
 488                  * libc be deleted.  It is possible that an auditors complete
 489                  * initialization fails, but there is presently no main link-map
 490                  * list.  As this libc has established the thread pointer, don't
 491                  * delete this libc, otherwise the initialization of libc on the
 492                  * main link-map can be compromised during its threads
 493                  * initialization.
 494                  */
 495                 if (((lml->lm_flags & LML_FLG_BASELM) == 0) &&
 496                     ((rtld_flags2 & RT_FL2_PLMSETUP) == 0))
 497                         MODE(lml->lm_lcs[CI_THRINIT].lc_lmp) |= RTLD_NODELETE;
 498         }
 499 }
 500 
 501 thread_t
 502 rt_thr_self()
 503 {
 504         thread_t        (*fptr)(void);
 505 
 506         if ((fptr = (thread_t (*)())glcs[CI_THR_SELF].lc_un.lc_func) != NULL)
 507                 return ((*fptr)());
 508 
 509         return (1);
 510 }
 511 
 512 int
 513 rt_mutex_lock(Rt_lock *mp)
 514 {
 515         return (_lwp_mutex_lock((lwp_mutex_t *)mp));
 516 }
 517 
 518 int
 519 rt_mutex_unlock(Rt_lock *mp)
 520 {
 521         return (_lwp_mutex_unlock((lwp_mutex_t *)mp));
 522 }
 523 
 524 /*
 525  * Test whether we're in a libc critical region.  Certain function references,
 526  * like the "mem*" family, might require binding.  Although these functions can
 527  * safely bind to auxiliary filtees, they should not be captured by auditors.
 528  */
 529 int
 530 rt_critical()
 531 {
 532         int     (*fptr)(void);
 533 
 534         if ((fptr = glcs[CI_CRITICAL].lc_un.lc_func) != NULL)
 535                 return ((*fptr)());
 536 
 537         return (0);
 538 }
 539 
 540 /*
 541  * Mutex interfaces to resolve references from any objects extracted from
 542  * libc_pic.a.  Note, as ld.so.1 is essentially single threaded these can be
 543  * noops.
 544  */
 545 #pragma weak lmutex_lock = mutex_lock
 546 /* ARGSUSED */
 547 int
 548 mutex_lock(mutex_t *mp)
 549 {
 550         return (0);
 551 }
 552 
 553 #pragma weak lmutex_unlock = mutex_unlock
 554 /* ARGSUSED */
 555 int
 556 mutex_unlock(mutex_t *mp)
 557 {
 558         return (0);
 559 }
 560 
 561 /* ARGSUSED */
 562 int
 563 mutex_init(mutex_t *mp, int type, void *arg)
 564 {
 565         return (0);
 566 }
 567 
 568 /* ARGSUSED */
 569 int
 570 mutex_destroy(mutex_t *mp)
 571 {
 572         return (0);
 573 }
 574 
 575 /*
 576  * This is needed to satisfy sysconf() (case _SC_THREAD_STACK_MIN)
 577  */
 578 size_t
 579 thr_min_stack()
 580 {
 581         return (sizeof (uintptr_t) * 1024);
 582 }
 583 
 584 /*
 585  * Local str[n]casecmp() interfaces for the dynamic linker,
 586  * to avoid problems when linking with libc_pic.a
 587  */
 588 int
 589 strcasecmp(const char *s1, const char *s2)
 590 {
 591         extern int ascii_strcasecmp(const char *, const char *);
 592 
 593         return (ascii_strcasecmp(s1, s2));
 594 }
 595 
 596 int
 597 strncasecmp(const char *s1, const char *s2, size_t n)
 598 {
 599         extern int ascii_strncasecmp(const char *, const char *, size_t);
 600 
 601         return (ascii_strncasecmp(s1, s2, n));
 602 }
 603 
 604 /*
 605  * The following functions are cancellation points in libc.
 606  * They are called from other functions in libc that we extract
 607  * and use directly.  We don't do cancellation while we are in
 608  * the dynamic linker, so we redefine these to call the primitive,
 609  * non-cancellation interfaces.
 610  */
 611 int
 612 close(int fildes)
 613 {
 614         extern int __close(int);
 615 
 616         return (__close(fildes));
 617 }
 618 
 619 int
 620 fcntl(int fildes, int cmd, ...)
 621 {
 622         extern int __fcntl(int, int, ...);
 623         intptr_t arg;
 624         va_list ap;
 625 
 626         va_start(ap, cmd);
 627         arg = va_arg(ap, intptr_t);
 628         va_end(ap);
 629         return (__fcntl(fildes, cmd, arg));
 630 }
 631 
 632 int
 633 open(const char *path, int oflag, ...)
 634 {
 635         extern int __open(const char *, int, mode_t);
 636         mode_t mode;
 637         va_list ap;
 638 
 639         va_start(ap, oflag);
 640         mode = va_arg(ap, mode_t);
 641         va_end(ap);
 642         return (__open(path, oflag, mode));
 643 }
 644 
 645 int
 646 openat(int fd, const char *path, int oflag, ...)
 647 {
 648         extern int __openat(int, const char *, int, mode_t);
 649         mode_t mode;
 650         va_list ap;
 651 
 652         va_start(ap, oflag);
 653         mode = va_arg(ap, mode_t);
 654         va_end(ap);
 655         return (__openat(fd, path, oflag, mode));
 656 }
 657 
 658 ssize_t
 659 read(int fd, void *buf, size_t size)
 660 {
 661         extern ssize_t __read(int, void *, size_t);
 662         return (__read(fd, buf, size));
 663 }
 664 
 665 ssize_t
 666 write(int fd, const void *buf, size_t size)
 667 {
 668         extern ssize_t __write(int, const void *, size_t);
 669         return (__write(fd, buf, size));
 670 }