Print this page
NEX-6532 allow specifying individual IP addresses without @ prefix in NFS access lists
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
NEX-6673 possible NULL pointer dereference in mountd`mount
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
NEX-4116 mountd: The IP to name translation is usually not needed in nfsauth_access()
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-4603 mountd: Compile warnings cleanup
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-2614 Add non-interactive mode for ypinit
NEX-2394 mountd() door services are sub-optimal in large... (redux)
NEX-1974 Support for more than 16 groups with AUTH_SYS
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-2394 mountd() door services are sub-optimal in large scale deployments
NEX-2526 mountd consumes an inordinate amount of memory
NEX-2502 4.0.3 RC4 Unable to mount NFS shares
Revert "NEX-2394 mountd() door services are sub-optimal in large scale deployments".
This reverts commit c6e1673e3a4b8ba866c77dee7b8f03f858be07d6.
The fix for NEX-2394 worked fine when putting the mountd binary in 4.0.2,
but needs additional work in a 4.0.3 environment
NEX-2394 mountd() door services are sub-optimal in large scale deployments
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Ryuji Masuda <ryuji.masuda@nexenta.com>
Reviewed by: Kirill Davydychev <kirill.davydychev@nexenta.com>
NEX-1128 NFS server: Generic uid and gid remapping for AUTH_SYS
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
OS-141 mountd(1m) needs to be able to set listen backlog
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
OS-134 mountd(1m): Remove limit of FDs in RPC server
Reviewed by: Michael Tsymbalyuk <michael.tsymbalyuk@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
OS-133 mountd: Busy do_logging_queue() eats memory
Reviewed by: Michael Tsymbalyuk <michael.tsymbalyuk@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
OS-131 mountd(1m) leaks nd_hostservlist in do_logging_queue()
Reviewed by: Ilya Usvyatsky <ilya.usvyatsky@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
OS-20 share_nfs(1m) charset handling is unreliable
OS-22 Page fault at nfscmd_dropped_entrysize+0x1e()
OS-23 NFSv2/3/4: READDIR responses are inconsistent when charset conversion fails
OS-24 rfs3_readdir(): Issues related to nfscmd_convdirent()
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/fs.d/nfs/mountd/mountd.c
          +++ new/usr/src/cmd/fs.d/nfs/mountd/mountd.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  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  /*
  23   23   * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2016 Nexenta Systems, Inc.
  24   25   * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
  25      - * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  26   26   */
  27   27  
  28   28  /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T     */
  29   29  /*        All Rights Reserved   */
  30   30  
  31   31  /*
  32   32   * Portions of this source code were derived from Berkeley 4.3 BSD
  33   33   * under license from the Regents of the University of California.
  34   34   */
  35   35  
↓ open down ↓ 20 lines elided ↑ open up ↑
  56   56  #include <sys/resource.h>
  57   57  #include <signal.h>
  58   58  #include <locale.h>
  59   59  #include <unistd.h>
  60   60  #include <errno.h>
  61   61  #include <sys/socket.h>
  62   62  #include <netinet/in.h>
  63   63  #include <arpa/inet.h>
  64   64  #include <netdb.h>
  65   65  #include <thread.h>
       66 +#include <pthread.h>
  66   67  #include <assert.h>
  67   68  #include <priv_utils.h>
  68   69  #include <nfs/auth.h>
  69   70  #include <nfs/nfssys.h>
  70   71  #include <nfs/nfs.h>
  71   72  #include <nfs/nfs_sec.h>
  72   73  #include <rpcsvc/daemon_utils.h>
  73   74  #include <deflt.h>
  74   75  #include "../../fslib.h"
  75   76  #include <sharefs/share.h>
↓ open down ↓ 5 lines elided ↑ open up ↑
  81   82  #include <libtsnet.h>
  82   83  #include <sys/sdt.h>
  83   84  #include <libscf.h>
  84   85  #include <limits.h>
  85   86  #include <sys/nvpair.h>
  86   87  #include <attr.h>
  87   88  #include "smfcfg.h"
  88   89  #include <pwd.h>
  89   90  #include <grp.h>
  90   91  #include <alloca.h>
       92 +#include <atomic.h>
  91   93  
  92   94  extern int daemonize_init(void);
  93   95  extern void daemonize_fini(int);
  94   96  
  95   97  extern int _nfssys(int, void *);
  96   98  
  97   99  struct sh_list *share_list;
  98  100  
  99  101  rwlock_t sharetab_lock;         /* lock to protect the cached sharetab */
 100  102  static mutex_t mnttab_lock;     /* prevent concurrent mnttab readers */
↓ open down ↓ 21 lines elided ↑ open up ↑
 122  124  static int verbose;
 123  125  static int rejecting;
 124  126  static int mount_vers_min = MOUNTVERS;
 125  127  static int mount_vers_max = MOUNTVERS3;
 126  128  static int mountd_port = 0;
 127  129  
 128  130  extern void nfscmd_func(void *, char *, size_t, door_desc_t *, uint_t);
 129  131  
 130  132  thread_t        nfsauth_thread;
 131  133  thread_t        cmd_thread;
 132      -thread_t        logging_thread;
 133  134  
      135 +/*
      136 + * The following logging and BSM related data structs
      137 + * are only used when mountd_bsm_audit is TRUE; this
      138 + * is done by specifying the undocumented -A flag to
      139 + * mountd(1m).
      140 + */
      141 +static bool_t   mountd_bsm_audit = FALSE;
      142 +
 134  143  typedef struct logging_data {
 135  144          char                    *ld_host;
 136  145          char                    *ld_path;
 137  146          char                    *ld_rpath;
 138  147          int                     ld_status;
 139  148          char                    *ld_netid;
 140  149          struct netbuf           *ld_nb;
 141  150          struct logging_data     *ld_next;
 142  151  } logging_data;
 143  152  
 144  153  static logging_data *logging_head = NULL;
 145  154  static logging_data *logging_tail = NULL;
 146  155  
      156 +#define MOUNTD_STKSZ    (16 * 1024)     /* 16KB Stacks */
      157 +static  uint32_t        nm_thrds = 0;
      158 +static  uint32_t        mx_thrds = 2;   /* fallback default: see main() */
      159 +
      160 +static  thread_key_t    door_key;
      161 +static  mutex_t         door_lock;
      162 +static  int             cmd_door = -1;
      163 +static  cond_t          cdoor_cv;
      164 +static  int             auth_door = -1;
      165 +static  cond_t          adoor_cv;
      166 +
      167 +typedef enum {
      168 +        UNKNOWN_FUNC    = 0,
      169 +        NFSAUTH_FUNC    = 1,
      170 +        NFSCMD_FUNC     = 2
      171 +} dr_cmd_t;
      172 +
 147  173  /*
 148  174   * Our copy of some system variables obtained using sysconf(3c)
 149  175   */
 150  176  static long ngroups_max;        /* _SC_NGROUPS_MAX */
 151  177  static long pw_size;            /* _SC_GETPW_R_SIZE_MAX */
 152  178  
      179 +static char *
      180 +cmd2str(dr_cmd_t t)
      181 +{
      182 +        switch (t) {
      183 +        case NFSAUTH_FUNC:
      184 +                return ("NFSAUTH_FUNC");
      185 +
      186 +        case NFSCMD_FUNC:
      187 +                return ("NFSCMD_FUNC");
      188 +
      189 +        case UNKNOWN_FUNC:
      190 +        default:
      191 +                return ("UNKNOWN_FUNC");
      192 +        }
      193 +}
      194 +
      195 +void *
      196 +mntd_thr_start(void *arg)
      197 +{
      198 +        dr_cmd_t        *cp = (dr_cmd_t *)arg;
      199 +        dr_cmd_t         cmd = *cp;
      200 +        static void     *value;
      201 +        int              dfd = 0;
      202 +
      203 +        value = (nm_thrds >= mx_thrds) ? (void *)1 : (void *)0;
      204 +        (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
      205 +        (void) thr_setspecific(door_key, value);
      206 +
      207 +        switch (cmd) {
      208 +        case NFSAUTH_FUNC:
      209 +                (void) mutex_lock(&door_lock);
      210 +                while (auth_door == -1)
      211 +                        cond_wait(&adoor_cv, &door_lock);
      212 +                dfd = auth_door;
      213 +                (void) mutex_unlock(&door_lock);
      214 +                break;
      215 +
      216 +        case NFSCMD_FUNC:
      217 +                (void) mutex_lock(&door_lock);
      218 +                while (cmd_door == -1)
      219 +                        cond_wait(&cdoor_cv, &door_lock);
      220 +                dfd = cmd_door;
      221 +                (void) mutex_unlock(&door_lock);
      222 +                break;
      223 +
      224 +        default:
      225 +                syslog(LOG_NOTICE, "mntd_thr_start: %s", cmd2str(cmd));
      226 +                free(cp);
      227 +                thr_exit(NULL);
      228 +        }
      229 +
      230 +        if (door_bind(dfd) < 0) {
      231 +                syslog(LOG_ERR, "Unable to bind door for %s: %m", cmd2str(cmd));
      232 +                exit(20);
      233 +        }
      234 +#ifdef  DEBUG
      235 +        syslog(LOG_NOTICE, "%s Door Bound Successfully", cmd2str(cmd));
      236 +#endif
      237 +        free(cp);
      238 +        door_return(NULL, 0, NULL, 0);
      239 +
      240 +        /* NOTREACHED */
      241 +        return (NULL);
      242 +}
      243 +
      244 +/*
      245 + * Manages stacksize and threadpool
      246 + */
      247 +static void
      248 +mntd_thr_create(door_info_t *dp)
      249 +{
      250 +        thread_t         tid;
      251 +        int              num = 0;
      252 +        int              rc = 0;
      253 +        size_t           stksz = MOUNTD_STKSZ;
      254 +        long             flags = THR_DETACHED;
      255 +        void            *proc;
      256 +        dr_cmd_t        *cp;
      257 +#ifdef  DEBUG
      258 +        char             func[1024] = {0};
      259 +#endif
      260 +
      261 +        if (dp == NULL) {
      262 +                syslog(LOG_NOTICE, "mntd_thr_create: dp == NULL");
      263 +                return;
      264 +        }
      265 +        proc = (void *)(uintptr_t)dp->di_proc;
      266 +
      267 +        if ((cp = (dr_cmd_t *)malloc(sizeof (dr_cmd_t))) == (dr_cmd_t *)NULL) {
      268 +                syslog(LOG_ERR, "mntd_thr_create: %m");
      269 +                return;
      270 +        }
      271 +
      272 +#ifdef  DEBUG
      273 +        (void) addrtosymstr(proc, func, sizeof (func));
      274 +        syslog(LOG_NOTICE, "mntd_thr_create: func = %s", func);
      275 +#endif
      276 +
      277 +        if (proc == (void *)nfsauth_func)
      278 +                *cp = NFSAUTH_FUNC;
      279 +        else if (proc == (void *)nfscmd_func)
      280 +                *cp = NFSCMD_FUNC;
      281 +        else {
      282 +                free(cp);
      283 +                return;
      284 +        }
      285 +
      286 +        if ((num = atomic_inc_32_nv(&nm_thrds)) > mx_thrds) {
      287 +                atomic_dec_32(&nm_thrds);
      288 +                num -= 1;
      289 +#ifdef  DEBUG
      290 +                syslog(LOG_ERR,
      291 +                    "mntd_thr_create: %d threads already active", num);
      292 +#endif
      293 +                free(cp);
      294 +                return;
      295 +        }
      296 +
      297 +        rc = thr_create(NULL, stksz, mntd_thr_start, (void *)cp, flags, &tid);
      298 +        if (rc != 0) {
      299 +                atomic_dec_32(&nm_thrds);
      300 +                syslog(LOG_ERR, "mntd_thr_create: %m");
      301 +                free(cp);
      302 +                return;
      303 +        }
      304 +#ifdef  DEBUG
      305 +        syslog(LOG_NOTICE,
      306 +            "mntd_thr_create: tid %d created (nm_thrds = %d)", tid, nm_thrds);
      307 +#endif
      308 +}
      309 +
      310 +static void
      311 +mntd_thr_destroy(void *arg)
      312 +{
      313 +        atomic_dec_32(&nm_thrds);
      314 +#ifdef  DEBUG
      315 +        syslog(LOG_NOTICE, "mntd_thr_destroy: (nm_thrds = %d)", nm_thrds);
      316 +#endif
      317 +}
      318 +
 153  319  /* ARGSUSED */
 154  320  static void *
 155  321  nfsauth_svc(void *arg)
 156  322  {
 157      -        int     doorfd = -1;
 158  323          uint_t  darg;
      324 +        uint_t  flags = (DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_REFUSE_DESC);
 159  325  #ifdef DEBUG
 160  326          int     dfd;
 161  327  #endif
 162  328  
 163      -        if ((doorfd = door_create(nfsauth_func, NULL,
 164      -            DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
 165      -                syslog(LOG_ERR, "Unable to create door: %m\n");
      329 +        /* register 'nfsauth_func' as the new door service */
      330 +        (void) mutex_lock(&door_lock);
      331 +        auth_door = door_create(nfsauth_func, NULL, flags);
      332 +        (void) mutex_unlock(&door_lock);
      333 +
      334 +        if (auth_door < 0) {
      335 +                syslog(LOG_ERR, "nfsauth_svc: %m");
 166  336                  exit(10);
 167  337          }
 168  338  
 169  339  #ifdef DEBUG
 170  340          /*
 171  341           * Create a file system path for the door
 172  342           */
 173  343          if ((dfd = open(MOUNTD_DOOR, O_RDWR|O_CREAT|O_TRUNC,
 174  344              S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
 175  345                  syslog(LOG_ERR, "Unable to open %s: %m\n", MOUNTD_DOOR);
 176      -                (void) close(doorfd);
      346 +                (void) close(auth_door);
 177  347                  exit(11);
 178  348          }
 179  349  
 180  350          /*
 181  351           * Clean up any stale namespace associations
 182  352           */
 183  353          (void) fdetach(MOUNTD_DOOR);
 184  354  
 185  355          /*
 186  356           * Register in namespace to pass to the kernel to door_ki_open
 187  357           */
 188      -        if (fattach(doorfd, MOUNTD_DOOR) == -1) {
      358 +        if (fattach(auth_door, MOUNTD_DOOR) == -1) {
 189  359                  syslog(LOG_ERR, "Unable to fattach door: %m\n");
 190  360                  (void) close(dfd);
 191      -                (void) close(doorfd);
      361 +                (void) close(auth_door);
 192  362                  exit(12);
 193  363          }
 194  364          (void) close(dfd);
 195  365  #endif
 196  366  
 197  367          /*
 198  368           * Must pass the doorfd down to the kernel.
 199  369           */
 200      -        darg = doorfd;
      370 +        darg = auth_door;
 201  371          (void) _nfssys(MOUNTD_ARGS, &darg);
 202  372  
 203  373          /*
      374 +         * Signal thread that kernel has door descriptor
      375 +         */
      376 +        (void) mutex_lock(&door_lock);
      377 +        cond_signal(&adoor_cv);
      378 +        (void) mutex_unlock(&door_lock);
      379 +
      380 +        /*
 204  381           * Wait for incoming calls
 205  382           */
 206  383          /*CONSTCOND*/
 207  384          for (;;)
 208  385                  (void) pause();
 209  386  
 210  387          /*NOTREACHED*/
 211  388          syslog(LOG_ERR, gettext("Door server exited"));
 212  389          return (NULL);
 213  390  }
 214  391  
 215  392  /*
 216  393   * NFS command service thread code for setup and handling of the
 217  394   * nfs_cmd requests for character set conversion and other future
 218  395   * events.
 219  396   */
 220      -
 221  397  static void *
 222  398  cmd_svc(void *arg)
 223  399  {
 224      -        int     doorfd = -1;
 225  400          uint_t  darg;
      401 +        uint_t  flags = (DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_REFUSE_DESC);
 226  402  
 227      -        if ((doorfd = door_create(nfscmd_func, NULL,
 228      -            DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
      403 +        /* register 'nfscmd_func' as the new door service */
      404 +        (void) mutex_lock(&door_lock);
      405 +        cmd_door = door_create(nfscmd_func, NULL, flags);
      406 +        (void) mutex_unlock(&door_lock);
      407 +
      408 +        if (cmd_door < 0) {
 229  409                  syslog(LOG_ERR, "Unable to create cmd door: %m\n");
 230  410                  exit(10);
 231  411          }
 232  412  
 233  413          /*
 234      -         * Must pass the doorfd down to the kernel.
      414 +         * Must pass the cmd_door down to the kernel.
 235  415           */
 236      -        darg = doorfd;
      416 +        darg = cmd_door;
 237  417          (void) _nfssys(NFSCMD_ARGS, &darg);
 238  418  
 239  419          /*
      420 +         * Signal thread that kernel has door descriptor
      421 +         */
      422 +        (void) mutex_lock(&door_lock);
      423 +        cond_signal(&cdoor_cv);
      424 +        (void) mutex_unlock(&door_lock);
      425 +
      426 +        /*
 240  427           * Wait for incoming calls
 241  428           */
 242  429          /*CONSTCOND*/
 243  430          for (;;)
 244  431                  (void) pause();
 245  432  
 246  433          /*NOTREACHED*/
 247  434          syslog(LOG_ERR, gettext("Cmd door server exited"));
 248  435          return (NULL);
 249  436  }
 250  437  
 251  438  static void
 252  439  free_logging_data(logging_data *lq)
 253  440  {
      441 +        assert(mountd_bsm_audit == TRUE);
      442 +
 254  443          if (lq != NULL) {
 255  444                  free(lq->ld_host);
 256  445                  free(lq->ld_netid);
 257  446  
 258  447                  if (lq->ld_nb != NULL) {
 259  448                          free(lq->ld_nb->buf);
 260  449                          free(lq->ld_nb);
 261  450                  }
 262  451  
 263  452                  free(lq->ld_path);
↓ open down ↓ 1 lines elided ↑ open up ↑
 265  454  
 266  455                  free(lq);
 267  456          }
 268  457  }
 269  458  
 270  459  static logging_data *
 271  460  remove_head_of_queue(void)
 272  461  {
 273  462          logging_data    *lq;
 274  463  
      464 +        assert(mountd_bsm_audit == TRUE);
      465 +
 275  466          /*
 276  467           * Pull it off the queue.
 277  468           */
 278  469          lq = logging_head;
 279  470          if (lq) {
 280  471                  logging_head = lq->ld_next;
 281  472  
 282  473                  /*
 283  474                   * Drained it.
 284  475                   */
↓ open down ↓ 4 lines elided ↑ open up ↑
 289  480  
 290  481          return (lq);
 291  482  }
 292  483  
 293  484  static void
 294  485  do_logging_queue(logging_data *lq)
 295  486  {
 296  487          int             cleared = 0;
 297  488          char            *host;
 298  489  
      490 +        assert(mountd_bsm_audit == TRUE);
      491 +
 299  492          while (lq) {
 300  493                  struct cln cln;
 301  494  
 302  495                  if (lq->ld_host == NULL) {
 303  496                          DTRACE_PROBE(mountd, name_by_lazy);
 304  497                          cln_init_lazy(&cln, lq->ld_netid, lq->ld_nb);
 305  498                          host = cln_gethost(&cln);
 306  499                  } else
 307  500                          host = lq->ld_host;
 308  501  
↓ open down ↓ 15 lines elided ↑ open up ↑
 324  517          }
 325  518  
 326  519          DTRACE_PROBE1(mountd, logging_cleared, cleared);
 327  520  }
 328  521  
 329  522  static void *
 330  523  logging_svc(void *arg)
 331  524  {
 332  525          logging_data    *lq;
 333  526  
      527 +        assert(mountd_bsm_audit == TRUE);
      528 +
 334  529          for (;;) {
 335  530                  (void) mutex_lock(&logging_queue_lock);
 336  531                  while (logging_head == NULL) {
 337  532                          (void) cond_wait(&logging_queue_cv,
 338  533                              &logging_queue_lock);
 339  534                  }
 340  535  
 341  536                  lq = remove_head_of_queue();
 342  537                  (void) mutex_unlock(&logging_queue_lock);
 343  538  
↓ open down ↓ 160 lines elided ↑ open up ↑
 504  699                      "failed, using default value");
 505  700          }
 506  701  
 507  702          ret = nfs_smf_get_iprop("mountd_port", &mountd_port,
 508  703              DEFAULT_INSTANCE, SCF_TYPE_INTEGER, NFSD);
 509  704          if (ret != SA_OK) {
 510  705                  syslog(LOG_ERR, "Reading of mountd_port from SMF "
 511  706                      "failed, using default value");
 512  707          }
 513  708  
 514      -        while ((c = getopt(argc, argv, "dvrm:p:")) != EOF) {
      709 +        while ((c = getopt(argc, argv, "dvrm:p:A")) != EOF) {
 515  710                  switch (c) {
 516  711                  case 'd':
 517  712                          debug++;
 518  713                          break;
 519  714                  case 'v':
 520  715                          verbose++;
 521  716                          break;
 522  717                  case 'r':
 523  718                          rejecting = 1;
 524  719                          break;
 525  720                  case 'm':
 526  721                          if (convert_int(&tmp, optarg) != 0 || tmp < 1) {
 527  722                                  (void) fprintf(stderr, "%s: invalid "
 528  723                                      "max_threads option, using defaults\n",
 529  724                                      argv[0]);
 530  725                                  break;
 531  726                          }
 532  727                          max_threads = tmp;
 533  728                          break;
      729 +                case 'A':
      730 +                        mountd_bsm_audit = TRUE;
 534  731                  case 'p':
 535  732                          if (convert_int(&tmp, optarg) != 0 || tmp < 1 ||
 536  733                              tmp > UINT16_MAX) {
 537  734                                  (void) fprintf(stderr, "%s: invalid port "
 538  735                                      "number\n", argv[0]);
 539  736                                  break;
 540  737                          }
 541  738                          mountd_port = tmp;
 542  739                          break;
 543  740                  default:
↓ open down ↓ 47 lines elided ↑ open up ↑
 591  788           */
 592  789          if (mount_vers_max > MOUNTVERS3)
 593  790                  mount_vers_max = MOUNTVERS3;
 594  791          if (mount_vers_min > mount_vers_max) {
 595  792                  fprintf(stderr, "server_versmin > server_versmax\n");
 596  793                  mount_vers_max = mount_vers_min;
 597  794          }
 598  795          (void) setlocale(LC_ALL, "");
 599  796          (void) rwlock_init(&sharetab_lock, USYNC_THREAD, NULL);
 600  797          (void) mutex_init(&mnttab_lock, USYNC_THREAD, NULL);
 601      -        (void) mutex_init(&logging_queue_lock, USYNC_THREAD, NULL);
 602      -        (void) cond_init(&logging_queue_cv, USYNC_THREAD, NULL);
      798 +        if (mountd_bsm_audit) {
      799 +                (void) mutex_init(&logging_queue_lock, USYNC_THREAD, NULL);
      800 +                (void) cond_init(&logging_queue_cv, USYNC_THREAD, NULL);
      801 +        }
 603  802  
 604  803          netgroup_init();
 605  804  
 606  805  #if !defined(TEXT_DOMAIN)
 607  806  #define TEXT_DOMAIN "SYS_TEST"
 608  807  #endif
 609  808          (void) textdomain(TEXT_DOMAIN);
 610  809  
 611  810          /* Don't drop core if the NFS module isn't loaded. */
 612  811          (void) signal(SIGSYS, SIG_IGN);
↓ open down ↓ 21 lines elided ↑ open up ↑
 634  833                  break;
 635  834          case -1:
 636  835                  fprintf(stderr, "error locking for %s: %s\n", MOUNTD,
 637  836                      strerror(errno));
 638  837                  exit(2);
 639  838          default:
 640  839                  /* daemon was already running */
 641  840                  exit(0);
 642  841          }
 643  842  
 644      -        audit_mountd_setup();   /* BSM */
      843 +        if (mountd_bsm_audit)
      844 +                audit_mountd_setup();   /* BSM */
 645  845  
 646  846          /*
 647  847           * Get required system variables
 648  848           */
 649  849          if ((ngroups_max = sysconf(_SC_NGROUPS_MAX)) == -1) {
 650  850                  syslog(LOG_ERR, "Unable to get _SC_NGROUPS_MAX");
 651  851                  exit(1);
 652  852          }
 653  853          if ((pw_size = sysconf(_SC_GETPW_R_SIZE_MAX)) == -1) {
 654  854                  syslog(LOG_ERR, "Unable to get _SC_GETPW_R_SIZE_MAX");
↓ open down ↓ 39 lines elided ↑ open up ↑
 694  894          if (listen_backlog > 0 && !rpc_control(__RPC_SVC_LSTNBKLOG_SET,
 695  895              &listen_backlog)) {
 696  896                  fprintf(stderr, "unable to set listen backlog\n");
 697  897                  exit(1);
 698  898          }
 699  899  
 700  900          /*
 701  901           * If max_threads was specified, then set the
 702  902           * maximum number of threads to the value specified.
 703  903           */
 704      -        if (max_threads > 0 && !rpc_control(RPC_SVC_THRMAX_SET, &max_threads)) {
 705      -                fprintf(stderr, "unable to set max_threads\n");
 706      -                exit(1);
      904 +        if (max_threads > 0) {
      905 +                if (!rpc_control(RPC_SVC_THRMAX_SET, &max_threads)) {
      906 +                        fprintf(stderr, "unable to set max_threads\n");
      907 +                        exit(1);
      908 +                }
      909 +                /* Default to one fourth of all threads */
      910 +                mx_thrds = (uint32_t)(max_threads / 4);
 707  911          }
 708  912  
 709  913          if (mountd_port < 0 || mountd_port > UINT16_MAX) {
 710  914                  fprintf(stderr, "unable to use specified port\n");
 711  915                  exit(1);
 712  916          }
 713  917  
 714  918          /*
 715  919           * Make sure to unregister any previous versions in case the
 716  920           * user is reconfiguring the server in interesting ways.
 717  921           */
 718  922          svc_unreg(MOUNTPROG, MOUNTVERS);
 719  923          svc_unreg(MOUNTPROG, MOUNTVERS_POSIX);
 720  924          svc_unreg(MOUNTPROG, MOUNTVERS3);
 721  925  
      926 +        (void) mutex_init(&door_lock, USYNC_THREAD, NULL);
      927 +        (void) cond_init(&adoor_cv, USYNC_THREAD, NULL);
      928 +        (void) cond_init(&cdoor_cv, USYNC_THREAD, NULL);
      929 +
      930 +        /* server function to create/optimize door threads */
      931 +        (void) door_server_create(mntd_thr_create);
      932 +        if (thr_keycreate(&door_key, mntd_thr_destroy) != 0) {
      933 +                fprintf(stderr, "thr_keycreate (server thread): %s\n",
      934 +                    strerror(errno));
      935 +                exit(3);
      936 +        }
      937 +
 722  938          /*
 723  939           * Create the nfsauth thread with same signal disposition
 724  940           * as the main thread. We need to create a separate thread
 725  941           * since mountd() will be both an RPC server (for remote
 726  942           * traffic) _and_ a doors server (for kernel upcalls).
 727  943           */
 728  944          if (thr_create(NULL, 0, nfsauth_svc, 0, thr_flags, &nfsauth_thread)) {
 729  945                  fprintf(stderr,
 730  946                      gettext("Failed to create NFSAUTH svc thread\n"));
 731  947                  exit(2);
↓ open down ↓ 10 lines elided ↑ open up ↑
 742  958                  exit(2);
 743  959          }
 744  960  
 745  961          /*
 746  962           * Create an additional thread to service the rmtab and
 747  963           * audit_mountd_mount logging for mount requests. Use the same
 748  964           * signal disposition as the main thread. We create
 749  965           * a separate thread to allow the mount request threads to
 750  966           * clear as soon as possible.
 751  967           */
 752      -        if (thr_create(NULL, 0, logging_svc, 0, thr_flags, &logging_thread)) {
 753      -                syslog(LOG_ERR, gettext("Failed to create LOGGING svc thread"));
 754      -                exit(2);
      968 +        if (mountd_bsm_audit) {
      969 +                if (thr_create(NULL, 0, logging_svc, 0, thr_flags, NULL)) {
      970 +                        syslog(LOG_ERR,
      971 +                            gettext("Failed to create LOGGING svc thread"));
      972 +                        exit(2);
      973 +                }
 755  974          }
 756  975  
 757  976          /*
 758  977           * Enumerate network transports and create service listeners
 759  978           * as appropriate for each.
 760  979           */
 761  980          if ((nc = setnetconfig()) == NULL) {
 762  981                  syslog(LOG_ERR, "setnetconfig failed: %m");
 763  982                  return (-1);
 764  983          }
↓ open down ↓ 80 lines elided ↑ open up ↑
 845 1064  
 846 1065  void
 847 1066  log_cant_reply_cln(struct cln *cln)
 848 1067  {
 849 1068          int saverrno;
 850 1069          char *host;
 851 1070  
 852 1071          saverrno = errno;       /* save error code */
 853 1072  
 854 1073          host = cln_gethost(cln);
 855      -        if (host == NULL)
 856      -                return;
 857 1074  
 858 1075          errno = saverrno;
 859 1076          if (errno == 0)
 860 1077                  syslog(LOG_ERR, "couldn't send reply to %s", host);
 861 1078          else
 862 1079                  syslog(LOG_ERR, "couldn't send reply to %s: %m", host);
 863 1080  }
 864 1081  
 865 1082  void
 866 1083  log_cant_reply(SVCXPRT *transp)
↓ open down ↓ 204 lines elided ↑ open up ↑
1071 1288   * able to add a node to the queue. If we are not, then
1072 1289   * it is up to the caller to go ahead and log the data.
1073 1290   */
1074 1291  static int
1075 1292  enqueue_logging_data(char *host, SVCXPRT *transp, char *path,
1076 1293      char *rpath, int status, int error)
1077 1294  {
1078 1295          logging_data    *lq;
1079 1296          struct netbuf   *nb;
1080 1297  
     1298 +        assert(mountd_bsm_audit == TRUE);
     1299 +
1081 1300          lq = (logging_data *)calloc(1, sizeof (logging_data));
1082 1301          if (lq == NULL)
1083 1302                  goto cleanup;
1084 1303  
1085 1304          /*
1086 1305           * We might not yet have the host...
1087 1306           */
1088 1307          if (host) {
1089 1308                  DTRACE_PROBE1(mountd, log_host, host);
1090 1309                  lq->ld_host = strdup(host);
↓ open down ↓ 57 lines elided ↑ open up ↑
1148 1367  
1149 1368  cleanup:
1150 1369  
1151 1370          free_logging_data(lq);
1152 1371  
1153 1372          return (FALSE);
1154 1373  }
1155 1374  
1156 1375  
1157 1376  #define CLN_CLNAMES     (1 << 0)
1158      -#define CLN_HOST        (1 << 1)
1159 1377  
1160 1378  static void
1161 1379  cln_init_common(struct cln *cln, SVCXPRT *transp, char *netid,
1162 1380      struct netbuf *nbuf)
1163 1381  {
1164 1382          if ((cln->transp = transp) != NULL) {
1165 1383                  assert(netid == NULL && nbuf == NULL);
1166 1384                  cln->netid = transp->xp_netid;
1167 1385                  cln->nbuf = svc_getrpccaller(transp);
1168 1386          } else {
1169 1387                  cln->netid = netid;
1170 1388                  cln->nbuf = nbuf;
1171 1389          }
1172 1390  
1173      -        cln->nconf = NULL;
1174 1391          cln->clnames = NULL;
1175      -        cln->host = NULL;
1176      -
1177 1392          cln->flags = 0;
     1393 +
     1394 +        bzero(cln->host, sizeof (cln->host));
     1395 +
     1396 +        if (cln->netid != NULL && cln->nbuf != NULL &&
     1397 +            (cln->nconf = getnetconfigent(cln->netid)) != NULL) {
     1398 +                if (strcmp(cln->nconf->nc_protofmly, NC_INET) == 0) {
     1399 +                        struct sockaddr_in *sa;
     1400 +                        /* LINTED pointer alignment */
     1401 +                        sa = (struct sockaddr_in *)(cln->nbuf->buf);
     1402 +                        (void) inet_ntop(AF_INET, &sa->sin_addr.s_addr,
     1403 +                            cln->host, sizeof (cln->host));
     1404 +                } else if (strcmp(cln->nconf->nc_protofmly, NC_INET6) == 0) {
     1405 +                        struct sockaddr_in6 *sa;
     1406 +                        /* LINTED pointer alignment */
     1407 +                        sa = (struct sockaddr_in6 *)(cln->nbuf->buf);
     1408 +                        (void) inet_ntop(AF_INET6, &sa->sin6_addr.s6_addr,
     1409 +                            cln->host, sizeof (cln->host));
     1410 +                }
     1411 +        }
     1412 +
     1413 +        if (strlen(cln->host) == 0)
     1414 +                (void) strlcpy(cln->host, "(unknown)", sizeof (cln->host));
1178 1415  }
1179 1416  
1180 1417  void
1181 1418  cln_init(struct cln *cln, SVCXPRT *transp)
1182 1419  {
1183 1420          cln_init_common(cln, transp, NULL, NULL);
1184 1421  }
1185 1422  
1186 1423  void
1187 1424  cln_init_lazy(struct cln *cln, char *netid, struct netbuf *nbuf)
↓ open down ↓ 2 lines elided ↑ open up ↑
1190 1427  }
1191 1428  
1192 1429  void
1193 1430  cln_fini(struct cln *cln)
1194 1431  {
1195 1432          if (cln->nconf != NULL)
1196 1433                  freenetconfigent(cln->nconf);
1197 1434  
1198 1435          if (cln->clnames != NULL)
1199 1436                  netdir_free(cln->clnames, ND_HOSTSERVLIST);
1200      -
1201      -        free(cln->host);
1202 1437  }
1203 1438  
1204 1439  struct netbuf *
1205 1440  cln_getnbuf(struct cln *cln)
1206 1441  {
1207 1442          return (cln->nbuf);
1208 1443  }
1209 1444  
1210 1445  struct nd_hostservlist *
1211 1446  cln_getclientsnames(struct cln *cln)
1212 1447  {
1213 1448          if ((cln->flags & CLN_CLNAMES) == 0) {
1214      -                /*
1215      -                 * nconf is not needed if we do not have nbuf (see
1216      -                 * cln_gethost() too), so we check for nbuf and in a case it is
1217      -                 * NULL we do not try to get nconf.
1218      -                 */
1219      -                if (cln->netid != NULL && cln->nbuf != NULL) {
1220      -                        cln->nconf = getnetconfigent(cln->netid);
1221      -                        if (cln->nconf == NULL)
1222      -                                syslog(LOG_ERR, "%s: getnetconfigent failed",
1223      -                                    cln->netid);
1224      -                }
1225      -
1226      -                if (cln->nconf != NULL && cln->nbuf != NULL)
     1449 +                if (cln->nconf != NULL && cln->nbuf != NULL) {
1227 1450                          (void) __netdir_getbyaddr_nosrv(cln->nconf,
1228 1451                              &cln->clnames, cln->nbuf);
1229      -
     1452 +                }
1230 1453                  cln->flags |= CLN_CLNAMES;
1231 1454          }
1232 1455  
1233 1456          return (cln->clnames);
1234 1457  }
1235 1458  
1236      -/*
1237      - * Return B_TRUE if the host is already available at no cost
1238      - */
1239      -boolean_t
1240      -cln_havehost(struct cln *cln)
1241      -{
1242      -        return ((cln->flags & (CLN_CLNAMES | CLN_HOST)) != 0);
1243      -}
1244      -
1245 1459  char *
1246 1460  cln_gethost(struct cln *cln)
1247 1461  {
1248 1462          if (cln_getclientsnames(cln) != NULL)
1249 1463                  return (cln->clnames->h_hostservs[0].h_host);
1250 1464  
1251      -        if ((cln->flags & CLN_HOST) == 0) {
1252      -                if (cln->nconf == NULL || cln->nbuf == NULL) {
1253      -                        cln->host = strdup("(anon)");
1254      -                } else {
1255      -                        char host[MAXIPADDRLEN];
1256      -
1257      -                        if (strcmp(cln->nconf->nc_protofmly, NC_INET) == 0) {
1258      -                                struct sockaddr_in *sa;
1259      -
1260      -                                /* LINTED pointer alignment */
1261      -                                sa = (struct sockaddr_in *)(cln->nbuf->buf);
1262      -                                (void) inet_ntoa_r(sa->sin_addr, host);
1263      -
1264      -                                cln->host = strdup(host);
1265      -                        } else if (strcmp(cln->nconf->nc_protofmly,
1266      -                            NC_INET6) == 0) {
1267      -                                struct sockaddr_in6 *sa;
1268      -
1269      -                                /* LINTED pointer alignment */
1270      -                                sa = (struct sockaddr_in6 *)(cln->nbuf->buf);
1271      -                                (void) inet_ntop(AF_INET6,
1272      -                                    sa->sin6_addr.s6_addr,
1273      -                                    host, INET6_ADDRSTRLEN);
1274      -
1275      -                                cln->host = strdup(host);
1276      -                        } else {
1277      -                                syslog(LOG_ERR, gettext("Client's address is "
1278      -                                    "neither IPv4 nor IPv6"));
1279      -
1280      -                                cln->host = strdup("(anon)");
1281      -                        }
1282      -                }
1283      -
1284      -                cln->flags |= CLN_HOST;
1285      -        }
1286      -
1287 1465          return (cln->host);
1288 1466  }
1289 1467  
1290 1468  /*
1291 1469   * Check mount requests, add to mounted list if ok
1292 1470   */
1293 1471  static int
1294 1472  mount(struct svc_req *rqstp)
1295 1473  {
1296 1474          SVCXPRT *transp;
↓ open down ↓ 26 lines elided ↑ open up ↑
1323 1501  
1324 1502          /*
1325 1503           * Put off getting the name for the client until we
1326 1504           * need it. This is a performance gain. If we are logging,
1327 1505           * then we don't care about performance and might as well
1328 1506           * get the host name now in case we need to spit out an
1329 1507           * error message.
1330 1508           */
1331 1509          if (verbose) {
1332 1510                  DTRACE_PROBE(mountd, name_by_verbose);
1333      -                if ((host = cln_gethost(&cln)) == NULL) {
1334      -                        /*
1335      -                         * We failed to get a name for the client, even
1336      -                         * 'anon', probably because we ran out of memory.
1337      -                         * In this situation it doesn't make sense to
1338      -                         * allow the mount to succeed.
1339      -                         */
1340      -                        error = EACCES;
1341      -                        goto reply;
1342      -                }
     1511 +                host = cln_gethost(&cln);
1343 1512          }
1344 1513  
1345 1514          /*
1346 1515           * If the version being used is less than the minimum version,
1347 1516           * the filehandle translation should not be provided to the
1348 1517           * client.
1349 1518           */
1350 1519          if (rejecting || version < mount_vers_min) {
1351 1520                  if (verbose)
1352 1521                          syslog(LOG_NOTICE, "Rejected mount: %s for %s",
↓ open down ↓ 185 lines elided ↑ open up ↑
1538 1707                          error = MNT3ERR_NAMETOOLONG;
1539 1708  
1540 1709                  mountres3.fhs_status = error;
1541 1710                  if (!svc_sendreply(transp, xdr_mountres3, (char *)&mountres3))
1542 1711                          log_cant_reply_cln(&cln);
1543 1712  
1544 1713                  audit_status = mountres3.fhs_status;
1545 1714                  break;
1546 1715          }
1547 1716  
1548      -        if (cln_havehost(&cln))
     1717 +        if (host == NULL)
1549 1718                  host = cln_gethost(&cln);
1550 1719  
1551 1720          if (verbose)
1552      -                syslog(LOG_NOTICE, "MOUNT: %s %s %s",
1553      -                    (host == NULL) ? "unknown host" : host,
     1721 +                syslog(LOG_NOTICE, "MOUNT: %s %s %s", host,
1554 1722                      error ? "denied" : "mounted", path);
1555 1723  
1556      -        /*
1557      -         * If we can not create a queue entry, go ahead and do it
1558      -         * in the context of this thread.
1559      -         */
1560      -        enqueued = enqueue_logging_data(host, transp, path, rpath,
1561      -            audit_status, error);
1562      -        if (enqueued == FALSE) {
1563      -                if (host == NULL) {
1564      -                        DTRACE_PROBE(mountd, name_by_in_thread);
1565      -                        host = cln_gethost(&cln);
     1724 +        if (mountd_bsm_audit) {
     1725 +                /*
     1726 +                 * If we can not create a queue entry, go ahead and do it
     1727 +                 * in the context of this thread.
     1728 +                 */
     1729 +                enqueued = enqueue_logging_data(host, transp, path, rpath,
     1730 +                    audit_status, error);
     1731 +
     1732 +                if (enqueued == FALSE) {
     1733 +                        DTRACE_PROBE(mountd, logged_in_thread);
     1734 +                        audit_mountd_mount(host, path, audit_status); /* BSM */
1566 1735                  }
     1736 +        }
1567 1737  
1568      -                DTRACE_PROBE(mountd, logged_in_thread);
1569      -                audit_mountd_mount(host, path, audit_status); /* BSM */
1570      -                if (!error)
1571      -                        mntlist_new(host, rpath); /* add entry to mount list */
     1738 +        if (enqueued == FALSE && !error) {
     1739 +                /* Add entry to mount list */
     1740 +                mntlist_new(host, rpath);
1572 1741          }
1573 1742  
1574 1743          if (path != NULL)
1575 1744                  svc_freeargs(transp, xdr_dirpath, (caddr_t)&path);
1576 1745  
1577 1746          if (sh)
1578 1747                  sharefree(sh);
1579 1748  
1580 1749          cln_fini(&cln);
1581 1750  
↓ open down ↓ 386 lines elided ↑ open up ↑
1968 2137                                          return (-1);
1969 2138                                  } else if (ret == 1) {
1970 2139                                          return (response);
1971 2140                                  }
1972 2141                          }
1973 2142  
1974 2143                          goto next;
1975 2144                  }
1976 2145  
1977 2146                  /*
     2147 +                 * Before doing clients names lookup, check if it's individual
     2148 +                 * IP address specified without @ prefix.
     2149 +                 */
     2150 +                if (strcmp(gr, cln->host) == 0)
     2151 +                        return (response);
     2152 +
     2153 +                /*
1978 2154                   * No other checks can be performed if client address
1979 2155                   * can't be resolved.
1980 2156                   */
1981 2157                  if ((clnames = cln_getclientsnames(cln)) == NULL)
1982 2158                          goto next;
1983 2159  
1984 2160                  /* Otherwise loop through all client hostname aliases */
1985 2161                  for (i = 0; i < clnames->h_cnt; i++) {
1986 2162                          char *host = clnames->h_hostservs[i].h_host;
1987 2163  
↓ open down ↓ 1230 lines elided ↑ open up ↑
3218 3394                  return;
3219 3395          }
3220 3396  
3221 3397          cln_init(&cln, transp);
3222 3398  
3223 3399          errno = 0;
3224 3400          if (!svc_sendreply(transp, xdr_void, (char *)NULL))
3225 3401                  log_cant_reply_cln(&cln);
3226 3402  
3227 3403          host = cln_gethost(&cln);
3228      -        if (host == NULL) {
3229      -                /*
3230      -                 * Without the hostname we can't do audit or delete
3231      -                 * this host from the mount entries.
3232      -                 */
3233      -                svc_freeargs(transp, xdr_dirpath, (caddr_t)&path);
3234      -                return;
3235      -        }
3236 3404  
3237 3405          if (verbose)
3238 3406                  syslog(LOG_NOTICE, "UNMOUNT: %s unmounted %s", host, path);
3239 3407  
3240      -        audit_mountd_umount(host, path);
     3408 +        if (mountd_bsm_audit)
     3409 +                audit_mountd_umount(host, path);
3241 3410  
3242 3411          remove_path = rpath;    /* assume we will use the cannonical path */
3243 3412          if (realpath(path, rpath) == NULL) {
3244 3413                  if (verbose)
3245 3414                          syslog(LOG_WARNING, "UNMOUNT: realpath: %s: %m ", path);
3246 3415                  remove_path = path;     /* use path provided instead */
3247 3416          }
3248 3417  
3249 3418          mntlist_delete(host, remove_path);      /* remove from mount list */
3250 3419  
↓ open down ↓ 21 lines elided ↑ open up ↑
3272 3441           * We assume that this call is asynchronous and made via rpcbind
3273 3442           * callit routine.  Therefore return control immediately. The error
3274 3443           * causes rpcbind to remain silent, as opposed to every machine
3275 3444           * on the net blasting the requester with a response.
3276 3445           */
3277 3446          svcerr_systemerr(transp);
3278 3447  
3279 3448          cln_init(&cln, transp);
3280 3449  
3281 3450          host = cln_gethost(&cln);
3282      -        if (host == NULL) {
3283      -                /* Can't do anything without the name of the client */
3284      -                return;
3285      -        }
3286 3451  
3287 3452          /*
3288 3453           * Remove all hosts entries from mount list
3289 3454           */
3290 3455          mntlist_delete_all(host);
3291 3456  
3292 3457          if (verbose)
3293 3458                  syslog(LOG_NOTICE, "UNMOUNTALL: from %s", host);
3294 3459  
3295 3460          cln_fini(&cln);
↓ open down ↓ 54 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX