Print this page
    
Extra lint fixes
OS-5642 containerbuddy unable to fork while using syslog driver, causing container services to hang
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
OS-4781 would like to be able to add CT_PR_EV_EXIT to fatal event set of current contract
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/contract/process.c
          +++ new/usr/src/uts/common/contract/process.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ 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   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
       24 + * Copyright 2016 Joyent, Inc.
  24   25   */
  25   26  
  26   27  #include <sys/mutex.h>
  27   28  #include <sys/debug.h>
  28   29  #include <sys/types.h>
  29   30  #include <sys/param.h>
  30   31  #include <sys/kmem.h>
  31   32  #include <sys/thread.h>
  32   33  #include <sys/id_space.h>
  33   34  #include <sys/avl.h>
  34   35  #include <sys/list.h>
  35   36  #include <sys/sysmacros.h>
  36   37  #include <sys/proc.h>
  37   38  #include <sys/contract.h>
  38   39  #include <sys/contract_impl.h>
  39   40  #include <sys/contract/process.h>
  40   41  #include <sys/contract/process_impl.h>
  41   42  #include <sys/cmn_err.h>
  42   43  #include <sys/nvpair.h>
  43   44  #include <sys/policy.h>
  44   45  #include <sys/refstr.h>
  45   46  #include <sys/sunddi.h>
  46   47  
  47   48  /*
  48   49   * Process Contracts
  49   50   * -----------------
  50   51   *
  51   52   * Generally speaking, a process contract is a contract between a
  52   53   * process and a set of its descendent processes.  In some cases, when
  53   54   * the child processes outlive the author of the contract, the contract
  54   55   * may be held by (and therefore be between the child processes and) a
  55   56   * successor process which adopts the contract after the death of the
  56   57   * original author.
  57   58   *
  58   59   * The process contract adds two new concepts to the Solaris process
  59   60   * model.  The first is that a process contract forms a rigid fault
  60   61   * boundary around a set of processes.  Hardware, software, and even
  61   62   * administrator errors impacting a process in a process contract
  62   63   * generate specific events and can be requested to atomically shutdown
  63   64   * all processes in the contract.  The second is that a process
  64   65   * contract is a process collective whose leader is not a member of the
  65   66   * collective.  This means that the leader can reliably react to events
  66   67   * in the collective, and may also act upon the collective without
  67   68   * special casing itself.
  68   69   *
  69   70   * A composite outcome of these two concepts is that we can now create
  70   71   * a tree of process contracts, rooted at init(1M), which represent
  71   72   * services and subservices that are reliably observed and can be
  72   73   * restarted when fatal errors occur.  The service management framework
  73   74   * (SMF) realizes this structure.
  74   75   *
  75   76   * For more details, see the "restart agreements" case, PSARC 2003/193.
  76   77   *
  77   78   * There are four sets of routines in this file: the process contract
  78   79   * standard template operations, the process contract standard contract
  79   80   * operations, a couple routines used only by the contract subsystem to
  80   81   * handle process contracts' unique role as a temporary holder of
  81   82   * abandoned contracts, and the interfaces which allow the system to
  82   83   * create and act upon process contracts.  The first two are defined by
  83   84   * the contracts framework and won't be discussed further.  As for the
  84   85   * remaining two:
  85   86   *
  86   87   * Special framework interfaces
  87   88   * ----------------------------
  88   89   *
  89   90   * contract_process_accept - determines if a process contract is a
  90   91   *   regent, i.e. if it can inherit other contracts.
  91   92   *
  92   93   * contract_process_take - tells a regent process contract to inherit
  93   94   *   an abandoned contract
  94   95   *
  95   96   * contract_process_adopt - tells a regent process contract that a
  96   97   *   contract it has inherited is being adopted by a process.
  97   98   *
  98   99   * Process contract interfaces
  99  100   * ---------------------------
 100  101   *
 101  102   * contract_process_fork - called when a process is created; adds the
 102  103   *   new process to an existing contract or to a newly created one.
 103  104   *
 104  105   * contract_process_exit - called when a process exits
 105  106   *
 106  107   * contract_process_core - called when a process would have dumped core
 107  108   *   (even if a core file wasn't generated)
 108  109   *
 109  110   * contract_process_hwerr - called when a process was killed because of
 110  111   *   an uncorrectable hardware error
 111  112   *
 112  113   * contract_process_sig - called when a process was killed by a fatal
 113  114   *   signal sent by a process in another process contract
 114  115   *
 115  116   */
 116  117  
 117  118  ct_type_t *process_type;
 118  119  ctmpl_process_t *sys_process_tmpl;
 119  120  refstr_t *conp_svc_aux_default;
 120  121  
 121  122  /*
 122  123   * Macro predicates for determining when events should be sent and how.
 123  124   */
 124  125  #define EVSENDP(ctp, flag) \
 125  126          ((ctp->conp_contract.ct_ev_info | ctp->conp_contract.ct_ev_crit) & flag)
 126  127  
 127  128  #define EVINFOP(ctp, flag) \
 128  129          ((ctp->conp_contract.ct_ev_crit & flag) == 0)
 129  130  
 130  131  #define EVFATALP(ctp, flag) \
 131  132          (ctp->conp_ev_fatal & flag)
 132  133  
 133  134  
 134  135  /*
 135  136   * Process contract template implementation
 136  137   */
 137  138  
 138  139  /*
 139  140   * ctmpl_process_dup
 140  141   *
 141  142   * The process contract template dup entry point.  Other than the
 142  143   * to-be-subsumed contract, which must be held, this simply copies all
 143  144   * the fields of the original.
 144  145   */
 145  146  static struct ct_template *
 146  147  ctmpl_process_dup(struct ct_template *template)
 147  148  {
 148  149          ctmpl_process_t *new;
 149  150          ctmpl_process_t *old = template->ctmpl_data;
 150  151  
 151  152          new = kmem_alloc(sizeof (ctmpl_process_t), KM_SLEEP);
 152  153  
 153  154          ctmpl_copy(&new->ctp_ctmpl, template);
 154  155          new->ctp_ctmpl.ctmpl_data = new;
 155  156  
 156  157          new->ctp_subsume = old->ctp_subsume;
 157  158          if (new->ctp_subsume)
 158  159                  contract_hold(new->ctp_subsume);
 159  160          new->ctp_params = old->ctp_params;
 160  161          new->ctp_ev_fatal = old->ctp_ev_fatal;
 161  162          new->ctp_svc_fmri = old->ctp_svc_fmri;
 162  163          if (new->ctp_svc_fmri != NULL) {
 163  164                  refstr_hold(new->ctp_svc_fmri);
 164  165          }
 165  166          new->ctp_svc_aux = old->ctp_svc_aux;
 166  167          if (new->ctp_svc_aux != NULL) {
 167  168                  refstr_hold(new->ctp_svc_aux);
 168  169          }
 169  170  
 170  171          return (&new->ctp_ctmpl);
 171  172  }
 172  173  
 173  174  /*
 174  175   * ctmpl_process_free
 175  176   *
 176  177   * The process contract template free entry point.  Just releases a
 177  178   * to-be-subsumed contract and frees the template.
 178  179   */
 179  180  static void
 180  181  ctmpl_process_free(struct ct_template *template)
 181  182  {
 182  183          ctmpl_process_t *ctp = template->ctmpl_data;
 183  184  
 184  185          if (ctp->ctp_subsume)
 185  186                  contract_rele(ctp->ctp_subsume);
 186  187          if (ctp->ctp_svc_fmri != NULL) {
 187  188                  refstr_rele(ctp->ctp_svc_fmri);
 188  189          }
 189  190          if (ctp->ctp_svc_aux != NULL) {
 190  191                  refstr_rele(ctp->ctp_svc_aux);
 191  192          }
 192  193          kmem_free(template, sizeof (ctmpl_process_t));
 193  194  }
 194  195  
 195  196  /*
 196  197   * SAFE_EV is the set of events which a non-privileged process is
 197  198   * allowed to make critical but not fatal or if the PGRPONLY parameter
 198  199   * is set.  EXCESS tells us if "value", a critical event set, requires
 199  200   * additional privilege given the template "ctp".
 200  201   */
 201  202  #define SAFE_EV                 (CT_PR_EV_EMPTY)
 202  203  #define EXCESS(ctp, value)      \
 203  204          (((value) & ~((ctp)->ctp_ev_fatal | SAFE_EV)) || \
 204  205          (((value) & ~SAFE_EV) && (ctp->ctp_params & CT_PR_PGRPONLY)))
 205  206  
 206  207  /*
 207  208   * ctmpl_process_set
 208  209   *
 209  210   * The process contract template set entry point.  None of the terms
 210  211   * may be unconditionally set, and setting the parameters or fatal
 211  212   * event set may result in events being implicitly removed from to the
 212  213   * critical event set and added to the informative event set.  The
 213  214   * (admittedly subtle) reason we implicitly change the critical event
 214  215   * set when the parameter or fatal event set is modified but not the
 215  216   * other way around is because a change to the critical event set only
 216  217   * affects the contract's owner, whereas a change to the parameter set
 217  218   * and fatal set can affect the execution of the application running in
 218  219   * the contract (and should therefore be only made explicitly).  We
 219  220   * allow implicit changes at all so that setting contract terms doesn't
 220  221   * become a complex dance dependent on the template's initial state and
 221  222   * the desired terms.
 222  223   */
 223  224  static int
 224  225  ctmpl_process_set(struct ct_template *tmpl, ct_kparam_t *kparam,
 225  226      const cred_t *cr)
 226  227  {
 227  228          ctmpl_process_t *ctp = tmpl->ctmpl_data;
 228  229          ct_param_t *param = &kparam->param;
 229  230          contract_t *ct;
 230  231          int error;
 231  232          uint64_t param_value;
 232  233          char *str_value;
 233  234  
 234  235          if ((param->ctpm_id == CTPP_SVC_FMRI) ||
 235  236              (param->ctpm_id == CTPP_CREATOR_AUX)) {
 236  237                  str_value = (char *)kparam->ctpm_kbuf;
 237  238                  str_value[param->ctpm_size - 1] = '\0';
 238  239          } else {
 239  240                  if (param->ctpm_size < sizeof (uint64_t))
 240  241                          return (EINVAL);
 241  242                  param_value = *(uint64_t *)kparam->ctpm_kbuf;
 242  243                  /*
 243  244                   * No process contract parameters are > 32 bits.
 244  245                   * Unless it is a string.
 245  246                   */
 246  247                  if (param_value & ~UINT32_MAX)
 247  248                          return (EINVAL);
 248  249          }
 249  250  
 250  251          switch (param->ctpm_id) {
 251  252          case CTPP_SUBSUME:
 252  253                  if (param_value != 0) {
 253  254                          /*
 254  255                           * Ensure that the contract exists, that we
 255  256                           * hold the contract, and that the contract is
 256  257                           * empty.
 257  258                           */
 258  259                          ct = contract_type_ptr(process_type, param_value,
 259  260                              curproc->p_zone->zone_uniqid);
 260  261                          if (ct == NULL)
 261  262                                  return (ESRCH);
 262  263                          if (ct->ct_owner != curproc) {
 263  264                                  contract_rele(ct);
 264  265                                  return (EACCES);
 265  266                          }
 266  267                          if (((cont_process_t *)ct->ct_data)->conp_nmembers) {
 267  268                                  contract_rele(ct);
 268  269                                  return (ENOTEMPTY);
 269  270                          }
 270  271                  } else {
 271  272                          ct = NULL;
 272  273                  }
 273  274                  if (ctp->ctp_subsume)
 274  275                          contract_rele(ctp->ctp_subsume);
 275  276                  ctp->ctp_subsume = ct;
 276  277                  break;
 277  278          case CTPP_PARAMS:
 278  279                  if (param_value & ~CT_PR_ALLPARAM)
 279  280                          return (EINVAL);
 280  281                  ctp->ctp_params = param_value;
 281  282                  /*
 282  283                   * If an unprivileged process requests that
 283  284                   * CT_PR_PGRPONLY be set, remove any unsafe events from
 284  285                   * the critical event set and add them to the
 285  286                   * informative event set.
 286  287                   */
 287  288                  if ((ctp->ctp_params & CT_PR_PGRPONLY) &&
 288  289                      EXCESS(ctp, tmpl->ctmpl_ev_crit) &&
 289  290                      !secpolicy_contract_event_choice(cr)) {
 290  291                          tmpl->ctmpl_ev_info |= (tmpl->ctmpl_ev_crit & ~SAFE_EV);
 291  292                          tmpl->ctmpl_ev_crit &= SAFE_EV;
 292  293                  }
 293  294  
 294  295                  break;
 295  296          case CTPP_SVC_FMRI:
 296  297                  if (error = secpolicy_contract_identity(cr))
 297  298                          return (error);
 298  299                  if (ctp->ctp_svc_fmri != NULL)
 299  300                          refstr_rele(ctp->ctp_svc_fmri);
 300  301                  if (strcmp(CT_PR_SVC_DEFAULT, str_value) == 0)
 301  302                          ctp->ctp_svc_fmri = NULL;
 302  303                  else
 303  304                          ctp->ctp_svc_fmri =
 304  305                              refstr_alloc(str_value);
 305  306                  break;
 306  307          case CTPP_CREATOR_AUX:
 307  308                  if (ctp->ctp_svc_aux != NULL)
 308  309                          refstr_rele(ctp->ctp_svc_aux);
 309  310                  if (param->ctpm_size == 1) /* empty string */
 310  311                          ctp->ctp_svc_aux = NULL;
 311  312                  else
 312  313                          ctp->ctp_svc_aux =
 313  314                              refstr_alloc(str_value);
 314  315                  break;
 315  316          case CTP_EV_CRITICAL:
 316  317                  /*
 317  318                   * We simply don't allow adding events to the critical
 318  319                   * event set which aren't permitted by our policy or by
 319  320                   * privilege.
 320  321                   */
 321  322                  if (EXCESS(ctp, param_value) &&
 322  323                      (error = secpolicy_contract_event(cr)) != 0)
 323  324                          return (error);
 324  325                  tmpl->ctmpl_ev_crit = param_value;
 325  326                  break;
 326  327          case CTPP_EV_FATAL:
 327  328                  if (param_value & ~CT_PR_ALLFATAL)
 328  329                          return (EINVAL);
 329  330                  ctp->ctp_ev_fatal = param_value;
 330  331                  /*
 331  332                   * Check to see if an unprivileged process is
 332  333                   * requesting that events be removed from the fatal
 333  334                   * event set which are still in the critical event set.
 334  335                   */
 335  336                  if (EXCESS(ctp, tmpl->ctmpl_ev_crit) &&
 336  337                      !secpolicy_contract_event_choice(cr)) {
 337  338                          int allowed =
 338  339                              SAFE_EV | (ctp->ctp_params & CT_PR_PGRPONLY) ?
 339  340                              0 : ctp->ctp_ev_fatal;
 340  341                          tmpl->ctmpl_ev_info |= (tmpl->ctmpl_ev_crit & ~allowed);
 341  342                          tmpl->ctmpl_ev_crit &= allowed;
 342  343                  }
 343  344                  break;
 344  345          default:
 345  346                  return (EINVAL);
 346  347          }
 347  348  
 348  349          return (0);
 349  350  }
 350  351  
 351  352  /*
 352  353   * ctmpl_process_get
 353  354   *
 354  355   * The process contract template get entry point.  Simply fetches and
 355  356   * returns the requested term.
 356  357   */
 357  358  static int
 358  359  ctmpl_process_get(struct ct_template *template, ct_kparam_t *kparam)
 359  360  {
 360  361          ctmpl_process_t *ctp = template->ctmpl_data;
 361  362          ct_param_t *param = &kparam->param;
 362  363          uint64_t *param_value = kparam->ctpm_kbuf;
 363  364  
 364  365          if (param->ctpm_id == CTPP_SUBSUME ||
 365  366              param->ctpm_id == CTPP_PARAMS ||
 366  367              param->ctpm_id == CTPP_EV_FATAL) {
 367  368                  if (param->ctpm_size < sizeof (uint64_t))
 368  369                          return (EINVAL);
 369  370                  kparam->ret_size = sizeof (uint64_t);
 370  371          }
 371  372  
 372  373          switch (param->ctpm_id) {
 373  374          case CTPP_SUBSUME:
 374  375                  *param_value = ctp->ctp_subsume ?
 375  376                      ctp->ctp_subsume->ct_id : 0;
 376  377                  break;
 377  378          case CTPP_PARAMS:
 378  379                  *param_value = ctp->ctp_params;
 379  380                  break;
 380  381          case CTPP_SVC_FMRI:
 381  382                  if (ctp->ctp_svc_fmri == NULL) {
 382  383                          kparam->ret_size =
 383  384                              strlcpy((char *)kparam->ctpm_kbuf,
 384  385                              CT_PR_SVC_DEFAULT, param->ctpm_size);
 385  386                  } else {
 386  387                          kparam->ret_size =
 387  388                              strlcpy((char *)kparam->ctpm_kbuf,
 388  389                              refstr_value(ctp->ctp_svc_fmri), param->ctpm_size);
 389  390                  }
 390  391                  kparam->ret_size++;
 391  392                  break;
 392  393          case CTPP_CREATOR_AUX:
 393  394                  if (ctp->ctp_svc_aux == NULL) {
 394  395                          kparam->ret_size =
 395  396                              strlcpy((char *)kparam->ctpm_kbuf,
 396  397                              refstr_value(conp_svc_aux_default),
 397  398                              param->ctpm_size);
 398  399                  } else {
 399  400                          kparam->ret_size =
 400  401                              strlcpy((char *)kparam->ctpm_kbuf,
 401  402                              refstr_value(ctp->ctp_svc_aux), param->ctpm_size);
 402  403                  }
 403  404                  kparam->ret_size++;
 404  405                  break;
 405  406          case CTPP_EV_FATAL:
 406  407                  *param_value = ctp->ctp_ev_fatal;
 407  408                  break;
 408  409          default:
 409  410                  return (EINVAL);
 410  411          }
 411  412  
 412  413          return (0);
 413  414  }
 414  415  
 415  416  static ctmplops_t ctmpl_process_ops = {
 416  417          ctmpl_process_dup,              /* ctop_dup */
 417  418          ctmpl_process_free,             /* ctop_free */
 418  419          ctmpl_process_set,              /* ctop_set */
 419  420          ctmpl_process_get,              /* ctop_get */
 420  421          ctmpl_create_inval,             /* ctop_create */
 421  422          CT_PR_ALLEVENT
 422  423  };
 423  424  
 424  425  
 425  426  /*
 426  427   * Process contract implementation
 427  428   */
 428  429  
 429  430  /*
 430  431   * ctmpl_process_default
 431  432   *
 432  433   * The process contract default template entry point.  Creates a
 433  434   * process contract template with no parameters set, with informative
 434  435   * core and signal events, critical empty and hwerr events, and fatal
 435  436   * hwerr events.
 436  437   */
 437  438  static ct_template_t *
 438  439  contract_process_default(void)
 439  440  {
 440  441          ctmpl_process_t *new;
 441  442  
 442  443          new = kmem_alloc(sizeof (ctmpl_process_t), KM_SLEEP);
 443  444          ctmpl_init(&new->ctp_ctmpl, &ctmpl_process_ops, process_type, new);
 444  445  
 445  446          new->ctp_subsume = NULL;
 446  447          new->ctp_params = 0;
 447  448          new->ctp_ctmpl.ctmpl_ev_info = CT_PR_EV_CORE | CT_PR_EV_SIGNAL;
 448  449          new->ctp_ctmpl.ctmpl_ev_crit = CT_PR_EV_EMPTY | CT_PR_EV_HWERR;
 449  450          new->ctp_ev_fatal = CT_PR_EV_HWERR;
 450  451          new->ctp_svc_fmri = NULL;
 451  452          new->ctp_svc_aux = NULL;
 452  453  
 453  454          return (&new->ctp_ctmpl);
 454  455  }
 455  456  
 456  457  /*
 457  458   * contract_process_free
 458  459   *
 459  460   * The process contract free entry point.
 460  461   */
 461  462  static void
 462  463  contract_process_free(contract_t *ct)
 463  464  {
 464  465          cont_process_t *ctp = ct->ct_data;
 465  466          crfree(ctp->conp_cred);
 466  467          list_destroy(&ctp->conp_members);
 467  468          list_destroy(&ctp->conp_inherited);
 468  469          if (ctp->conp_svc_fmri != NULL) {
 469  470                  refstr_rele(ctp->conp_svc_fmri);
 470  471          }
 471  472          if (ctp->conp_svc_aux != NULL) {
 472  473                  refstr_rele(ctp->conp_svc_aux);
 473  474          }
 474  475          if (ctp->conp_svc_creator != NULL) {
 475  476                  refstr_rele(ctp->conp_svc_creator);
 476  477          }
 477  478          kmem_free(ctp, sizeof (cont_process_t));
 478  479  }
 479  480  
 480  481  /*
 481  482   * contract_process_cankill
 482  483   *
 483  484   * Determine if the contract author had or if the process generating
 484  485   * the event, sp, has adequate privileges to kill process tp.
 485  486   */
 486  487  static int
 487  488  contract_process_cankill(proc_t *tp, proc_t *sp, cont_process_t *ctp)
 488  489  {
 489  490          int cankill;
 490  491  
 491  492          mutex_enter(&tp->p_crlock);
 492  493          cankill = hasprocperm(tp->p_cred, ctp->conp_cred);
 493  494          mutex_exit(&tp->p_crlock);
 494  495          if (cankill || (sp && prochasprocperm(tp, sp, CRED())))
 495  496                  return (1);
 496  497  
 497  498          return (0);
 498  499  }
 499  500  
 500  501  /*
 501  502   * contract_process_kill
 502  503   *
 503  504   * Kills all processes in a contract, or all processes in the
 504  505   * intersection of a contract and ex's process group (if ex is non-NULL
 505  506   * and the contract's PGRPONLY parameter is set).  If checkpriv is
 506  507   * true, only those processes which may be signaled by the contract
 507  508   * author or ex are killed.
 508  509   */
 509  510  static void
 510  511  contract_process_kill(contract_t *ct, proc_t *ex, int checkpriv)
 511  512  {
 512  513          cont_process_t *ctp = ct->ct_data;
 513  514          proc_t *p;
 514  515          pid_t pgrp = -1;
 515  516  
 516  517          ASSERT(MUTEX_HELD(&ct->ct_lock));
 517  518  
 518  519          if (ex && (ctp->conp_params & CT_PR_PGRPONLY)) {
 519  520                  pgrp = ex->p_pgrp;
 520  521                  mutex_enter(&pidlock);
 521  522          }
 522  523  
 523  524          for (p = list_head(&ctp->conp_members); p != NULL;
 524  525              p = list_next(&ctp->conp_members, p)) {
 525  526                  if ((p == ex) ||
 526  527                      (pgrp != -1 && (p->p_stat == SIDL || p->p_pgrp != pgrp)) ||
 527  528                      (checkpriv && !contract_process_cankill(p, ex, ctp)))
 528  529                          continue;
 529  530  
 530  531                  psignal(p, SIGKILL);
 531  532          }
 532  533  
 533  534          if (pgrp != -1)
 534  535                  mutex_exit(&pidlock);
 535  536  }
 536  537  
 537  538  
 538  539  /*
 539  540   * contract_process_accept
 540  541   *
 541  542   * Tests if the process contract is willing to act as a regent for
 542  543   * inherited contracts.  Though brief and only called from one place,
 543  544   * this functionality is kept here to avoid including knowledge of
 544  545   * process contract implementation in the generic contract code.
 545  546   */
 546  547  int
 547  548  contract_process_accept(contract_t *parent)
 548  549  {
 549  550          cont_process_t *ctp = parent->ct_data;
 550  551  
 551  552          ASSERT(parent->ct_type == process_type);
 552  553  
 553  554          return (ctp->conp_params & CT_PR_REGENT);
 554  555  }
 555  556  
 556  557  /*
 557  558   * contract_process_take
 558  559   *
 559  560   * Executes the process contract side of inheriting a contract.
 560  561   */
 561  562  void
 562  563  contract_process_take(contract_t *parent, contract_t *child)
 563  564  {
 564  565          cont_process_t *ctp = parent->ct_data;
 565  566  
 566  567          ASSERT(MUTEX_HELD(&parent->ct_lock));
 567  568          ASSERT(MUTEX_HELD(&child->ct_lock));
 568  569          ASSERT(parent->ct_type == process_type);
 569  570          ASSERT(ctp->conp_params & CT_PR_REGENT);
 570  571  
 571  572          list_insert_head(&ctp->conp_inherited, child);
 572  573          ctp->conp_ninherited++;
 573  574  }
 574  575  
 575  576  /*
 576  577   * contract_process_adopt
 577  578   *
 578  579   * Executes the process contract side of adopting a contract.
 579  580   */
 580  581  void
 581  582  contract_process_adopt(contract_t *ct, proc_t *p)
 582  583  {
 583  584          cont_process_t *parent = p->p_ct_process;
 584  585  
 585  586          ASSERT(MUTEX_HELD(&parent->conp_contract.ct_lock));
 586  587          ASSERT(MUTEX_HELD(&ct->ct_lock));
 587  588  
 588  589          list_remove(&parent->conp_inherited, ct);
 589  590          parent->conp_ninherited--;
 590  591  
 591  592          /*
 592  593           * We drop the parent lock first because a) we are passing the
 593  594           * contract reference to the child, and b) contract_adopt
 594  595           * expects us to return with the contract lock held.
 595  596           */
 596  597          mutex_exit(&parent->conp_contract.ct_lock);
 597  598  }
 598  599  
 599  600  /*
 600  601   * contract_process_abandon
 601  602   *
 602  603   * The process contract abandon entry point.
 603  604   */
 604  605  static void
 605  606  contract_process_abandon(contract_t *ct)
 606  607  {
 607  608          cont_process_t *ctp = ct->ct_data;
 608  609  
 609  610          ASSERT(MUTEX_HELD(&ct->ct_lock));
 610  611  
 611  612          /*
 612  613           * Shall we stay or shall we go?
 613  614           */
 614  615          if (list_head(&ctp->conp_members) == NULL) {
 615  616                  contract_destroy(ct);
 616  617          } else {
 617  618                  /*
 618  619                   * Strictly speaking, we actually do orphan the contract.
 619  620                   * Assuming our credentials allow us to kill all
 620  621                   * processes in the contract, this is only temporary.
 621  622                   */
 622  623                  if (ctp->conp_params & CT_PR_NOORPHAN)
 623  624                          contract_process_kill(ct, NULL, B_TRUE);
 624  625                  contract_orphan(ct);
 625  626                  mutex_exit(&ct->ct_lock);
 626  627                  contract_rele(ct);
 627  628          }
 628  629  }
 629  630  
 630  631  /*
 631  632   * contract_process_destroy
 632  633   *
 633  634   * The process contract destroy entry point.
 634  635   */
 635  636  static void
 636  637  contract_process_destroy(contract_t *ct)
 637  638  {
 638  639          cont_process_t *ctp = ct->ct_data;
 639  640          contract_t *cct;
 640  641  
 641  642          ASSERT(MUTEX_HELD(&ct->ct_lock));
 642  643  
 643  644          /*
 644  645           * contract_destroy all empty children, kill or orphan the rest
 645  646           */
 646  647          while (cct = list_head(&ctp->conp_inherited)) {
 647  648                  mutex_enter(&cct->ct_lock);
 648  649  
 649  650                  ASSERT(cct->ct_state == CTS_INHERITED);
 650  651  
 651  652                  list_remove(&ctp->conp_inherited, cct);
 652  653                  ctp->conp_ninherited--;
 653  654                  cct->ct_regent = NULL;
 654  655                  cct->ct_type->ct_type_ops->contop_abandon(cct);
 655  656          }
 656  657  }
 657  658  
 658  659  /*
 659  660   * contract_process_status
 660  661   *
 661  662   * The process contract status entry point.
 662  663   */
 663  664  static void
 664  665  contract_process_status(contract_t *ct, zone_t *zone, int detail, nvlist_t *nvl,
 665  666      void *status, model_t model)
 666  667  {
 667  668          cont_process_t *ctp = ct->ct_data;
 668  669          uint32_t *pids, *ctids;
 669  670          uint_t npids, nctids;
 670  671          uint_t spids, sctids;
 671  672          ctid_t local_svc_zone_enter;
 672  673  
 673  674          if (detail == CTD_FIXED) {
 674  675                  mutex_enter(&ct->ct_lock);
 675  676                  contract_status_common(ct, zone, status, model);
 676  677                  local_svc_zone_enter = ctp->conp_svc_zone_enter;
 677  678                  mutex_exit(&ct->ct_lock);
 678  679          } else {
 679  680                  contract_t *cnext;
 680  681                  proc_t *pnext;
 681  682                  uint_t loc;
 682  683  
 683  684                  ASSERT(detail == CTD_ALL);
 684  685                  mutex_enter(&ct->ct_lock);
 685  686                  for (;;) {
 686  687                          spids = ctp->conp_nmembers + 5;
 687  688                          sctids = ctp->conp_ninherited + 5;
 688  689                          mutex_exit(&ct->ct_lock);
 689  690  
 690  691                          pids = kmem_alloc(spids * sizeof (uint32_t), KM_SLEEP);
 691  692                          ctids = kmem_alloc(sctids * sizeof (uint32_t),
 692  693                              KM_SLEEP);
 693  694  
 694  695                          mutex_enter(&ct->ct_lock);
 695  696                          npids = ctp->conp_nmembers;
 696  697                          nctids = ctp->conp_ninherited;
 697  698                          if (spids >= npids && sctids >= nctids)
 698  699                                  break;
 699  700  
 700  701                          kmem_free(pids, spids * sizeof (uint32_t));
 701  702                          kmem_free(ctids, sctids * sizeof (uint32_t));
 702  703                  }
 703  704                  contract_status_common(ct, zone, status, model);
 704  705                  for (loc = 0, cnext = list_head(&ctp->conp_inherited); cnext;
 705  706                      cnext = list_next(&ctp->conp_inherited, cnext))
 706  707                          ctids[loc++] = cnext->ct_id;
 707  708                  ASSERT(loc == nctids);
 708  709                  for (loc = 0, pnext = list_head(&ctp->conp_members); pnext;
 709  710                      pnext = list_next(&ctp->conp_members, pnext))
 710  711                          pids[loc++] = pnext->p_pid;
 711  712                  ASSERT(loc == npids);
 712  713                  local_svc_zone_enter = ctp->conp_svc_zone_enter;
 713  714                  mutex_exit(&ct->ct_lock);
 714  715          }
 715  716  
 716  717          /*
 717  718           * Contract terms are static; there's no need to hold the
 718  719           * contract lock while accessing them.
 719  720           */
 720  721          VERIFY(nvlist_add_uint32(nvl, CTPS_PARAMS, ctp->conp_params) == 0);
 721  722          VERIFY(nvlist_add_uint32(nvl, CTPS_EV_FATAL, ctp->conp_ev_fatal) == 0);
 722  723          if (detail == CTD_ALL) {
 723  724                  VERIFY(nvlist_add_uint32_array(nvl, CTPS_MEMBERS, pids,
 724  725                      npids) == 0);
 725  726                  VERIFY(nvlist_add_uint32_array(nvl, CTPS_CONTRACTS, ctids,
 726  727                      nctids) == 0);
 727  728                  VERIFY(nvlist_add_string(nvl, CTPS_CREATOR_AUX,
 728  729                      refstr_value(ctp->conp_svc_aux)) == 0);
 729  730                  VERIFY(nvlist_add_string(nvl, CTPS_SVC_CREATOR,
 730  731                      refstr_value(ctp->conp_svc_creator)) == 0);
 731  732                  kmem_free(pids, spids * sizeof (uint32_t));
 732  733                  kmem_free(ctids, sctids * sizeof (uint32_t));
 733  734          }
 734  735  
 735  736          /*
 736  737           * if we are in a local zone and svc_fmri was inherited from
 737  738           * the global zone, we provide fake svc_fmri and svc_ctid
 738  739           */
 739  740          if (local_svc_zone_enter == 0||
 740  741              zone->zone_uniqid == GLOBAL_ZONEUNIQID) {
 741  742                  if (detail > CTD_COMMON) {
 742  743                          VERIFY(nvlist_add_int32(nvl, CTPS_SVC_CTID,
 743  744                              ctp->conp_svc_ctid) == 0);
 744  745                  }
 745  746                  if (detail == CTD_ALL) {
 746  747                          VERIFY(nvlist_add_string(nvl, CTPS_SVC_FMRI,
 747  748                              refstr_value(ctp->conp_svc_fmri)) == 0);
 748  749                  }
 749  750          } else {
 750  751                  if (detail > CTD_COMMON) {
 751  752                          VERIFY(nvlist_add_int32(nvl, CTPS_SVC_CTID,
 752  753                              local_svc_zone_enter) == 0);
 753  754                  }
 754  755                  if (detail == CTD_ALL) {
 755  756                          VERIFY(nvlist_add_string(nvl, CTPS_SVC_FMRI,
 756  757                              CT_PR_SVC_FMRI_ZONE_ENTER) == 0);
 757  758                  }
 758  759          }
 759  760  }
 760  761  
 761  762  /*ARGSUSED*/
 762  763  static int
 763  764  contract_process_newct(contract_t *ct)
 764  765  {
 765  766          return (0);
 766  767  }
 767  768  
 768  769  /* process contracts don't negotiate */
 769  770  static contops_t contract_process_ops = {
 770  771          contract_process_free,          /* contop_free */
 771  772          contract_process_abandon,       /* contop_abandon */
 772  773          contract_process_destroy,       /* contop_destroy */
 773  774          contract_process_status,        /* contop_status */
 774  775          contract_ack_inval,             /* contop_ack */
 775  776          contract_ack_inval,             /* contop_nack */
 776  777          contract_qack_inval,            /* contop_qack */
 777  778          contract_process_newct          /* contop_newct */
 778  779  };
 779  780  
 780  781  /*
 781  782   * contract_process_init
 782  783   *
 783  784   * Initializes the process contract type.  Also creates a template for
 784  785   * use by newproc() when it creates user processes.
 785  786   */
 786  787  void
 787  788  contract_process_init(void)
 788  789  {
 789  790          process_type = contract_type_init(CTT_PROCESS, "process",
 790  791              &contract_process_ops, contract_process_default);
 791  792  
 792  793          /*
 793  794           * Create a template for use with init(1M) and other
 794  795           * kernel-started processes.
 795  796           */
 796  797          sys_process_tmpl = kmem_alloc(sizeof (ctmpl_process_t), KM_SLEEP);
 797  798          ctmpl_init(&sys_process_tmpl->ctp_ctmpl, &ctmpl_process_ops,
 798  799              process_type, sys_process_tmpl);
 799  800          sys_process_tmpl->ctp_subsume = NULL;
 800  801          sys_process_tmpl->ctp_params = CT_PR_NOORPHAN;
 801  802          sys_process_tmpl->ctp_ev_fatal = CT_PR_EV_HWERR;
 802  803          sys_process_tmpl->ctp_svc_fmri =
 803  804              refstr_alloc("svc:/system/init:default");
 804  805          sys_process_tmpl->ctp_svc_aux = refstr_alloc("");
 805  806          conp_svc_aux_default = sys_process_tmpl->ctp_svc_aux;
 806  807          refstr_hold(conp_svc_aux_default);
 807  808  }
 808  809  
 809  810  /*
 810  811   * contract_process_create
 811  812   *
 812  813   * create a process contract given template "tmpl" and parent process
 813  814   * "parent".  May fail and return NULL if project.max-contracts would
 814  815   * have been exceeded.
 815  816   */
 816  817  static cont_process_t *
 817  818  contract_process_create(ctmpl_process_t *tmpl, proc_t *parent, int canfail)
 818  819  {
 819  820          cont_process_t *ctp;
 820  821  
 821  822          ASSERT(tmpl != NULL);
 822  823  
 823  824          (void) contract_type_pbundle(process_type, parent);
 824  825  
 825  826          ctp = kmem_zalloc(sizeof (cont_process_t), KM_SLEEP);
 826  827  
 827  828          list_create(&ctp->conp_members, sizeof (proc_t),
 828  829              offsetof(proc_t, p_ct_member));
 829  830          list_create(&ctp->conp_inherited, sizeof (contract_t),
 830  831              offsetof(contract_t, ct_ctlist));
 831  832          mutex_enter(&tmpl->ctp_ctmpl.ctmpl_lock);
 832  833          ctp->conp_params = tmpl->ctp_params;
 833  834          ctp->conp_ev_fatal = tmpl->ctp_ev_fatal;
 834  835          crhold(ctp->conp_cred = CRED());
 835  836  
 836  837          if (contract_ctor(&ctp->conp_contract, process_type, &tmpl->ctp_ctmpl,
 837  838              ctp, (ctp->conp_params & CT_PR_INHERIT) ? CTF_INHERIT : 0,
 838  839              parent, canfail)) {
 839  840                  mutex_exit(&tmpl->ctp_ctmpl.ctmpl_lock);
 840  841                  contract_process_free(&ctp->conp_contract);
 841  842                  return (NULL);
 842  843          }
 843  844  
 844  845          /*
 845  846           * inherit svc_fmri if not defined by consumer. In this case, inherit
 846  847           * also svc_ctid to keep track of the contract id where
 847  848           * svc_fmri was set
 848  849           */
 849  850          if (tmpl->ctp_svc_fmri == NULL) {
 850  851                  ctp->conp_svc_fmri = parent->p_ct_process->conp_svc_fmri;
 851  852                  ctp->conp_svc_ctid = parent->p_ct_process->conp_svc_ctid;
 852  853                  ctp->conp_svc_zone_enter =
 853  854                      parent->p_ct_process->conp_svc_zone_enter;
 854  855          } else {
 855  856                  ctp->conp_svc_fmri = tmpl->ctp_svc_fmri;
 856  857                  ctp->conp_svc_ctid = ctp->conp_contract.ct_id;
 857  858                  /* make svc_zone_enter flag false when svc_fmri is set */
 858  859                  ctp->conp_svc_zone_enter = 0;
 859  860          }
 860  861          refstr_hold(ctp->conp_svc_fmri);
 861  862          /* set svc_aux to default value if not defined in template */
 862  863          if (tmpl->ctp_svc_aux == NULL) {
 863  864                  ctp->conp_svc_aux = conp_svc_aux_default;
 864  865          } else {
 865  866                  ctp->conp_svc_aux = tmpl->ctp_svc_aux;
 866  867          }
 867  868          refstr_hold(ctp->conp_svc_aux);
 868  869          /*
 869  870           * set svc_creator to execname
 870  871           * We special case pid0 because when newproc() creates
 871  872           * the init process, the p_user.u_comm field of sched's proc_t
 872  873           * has not been populated yet.
 873  874           */
 874  875          if (parent->p_pidp == &pid0) /* if the kernel is the creator */
 875  876                  ctp->conp_svc_creator = refstr_alloc("sched");
 876  877          else
 877  878                  ctp->conp_svc_creator = refstr_alloc(parent->p_user.u_comm);
 878  879  
 879  880          /*
 880  881           * Transfer subcontracts only after new contract is visible.
 881  882           * Also, only transfer contracts if the parent matches -- we
 882  883           * don't want to create a cycle in the tree of contracts.
 883  884           */
 884  885          if (tmpl->ctp_subsume && tmpl->ctp_subsume->ct_owner == parent) {
 885  886                  cont_process_t *sct = tmpl->ctp_subsume->ct_data;
 886  887                  contract_t *ct;
 887  888  
 888  889                  mutex_enter(&tmpl->ctp_subsume->ct_lock);
 889  890                  mutex_enter(&ctp->conp_contract.ct_lock);
 890  891                  while (ct = list_head(&sct->conp_inherited)) {
 891  892                          mutex_enter(&ct->ct_lock);
 892  893                          list_remove(&sct->conp_inherited, ct);
 893  894                          list_insert_tail(&ctp->conp_inherited, ct);
 894  895                          ct->ct_regent = &ctp->conp_contract;
 895  896                          mutex_exit(&ct->ct_lock);
 896  897                  }
 897  898                  ctp->conp_ninherited += sct->conp_ninherited;
 898  899                  sct->conp_ninherited = 0;
 899  900                  mutex_exit(&ctp->conp_contract.ct_lock);
 900  901                  mutex_exit(&tmpl->ctp_subsume->ct_lock);
 901  902  
 902  903                  /*
 903  904                   * Automatically abandon the contract.
 904  905                   */
 905  906                  (void) contract_abandon(tmpl->ctp_subsume, parent, 1);
 906  907          }
 907  908  
 908  909          mutex_exit(&tmpl->ctp_ctmpl.ctmpl_lock);
 909  910  
 910  911          return (ctp);
 911  912  }
 912  913  
 913  914  /*
 914  915   * contract_process_exit
 915  916   *
 916  917   * Called on process exit.  Removes process p from process contract
 917  918   * ctp.  Generates an exit event, if requested.  Generates an empty
 918  919   * event, if p is the last member of the the process contract and empty
 919  920   * events were requested.
 920  921   */
 921  922  void
 922  923  contract_process_exit(cont_process_t *ctp, proc_t *p, int exitstatus)
 923  924  {
 924  925          contract_t *ct = &ctp->conp_contract;
 925  926          ct_kevent_t *event;
 926  927          int empty;
 927  928  
 928  929          /*
 929  930           * Remove self from process contract.
 930  931           */
 931  932          mutex_enter(&ct->ct_lock);
 932  933          list_remove(&ctp->conp_members, p);
 933  934          ctp->conp_nmembers--;
 934  935          mutex_enter(&p->p_lock);        /* in case /proc is watching */
 935  936          p->p_ct_process = NULL;
 936  937          mutex_exit(&p->p_lock);
 937  938  
 938  939          /*
 939  940           * We check for emptiness before dropping the contract lock to
 940  941           * send the exit event, otherwise we could end up with two
 941  942           * empty events.
 942  943           */
 943  944          empty = (list_head(&ctp->conp_members) == NULL);
 944  945          if (EVSENDP(ctp, CT_PR_EV_EXIT)) {
 945  946                  nvlist_t *nvl;
 946  947  
 947  948                  mutex_exit(&ct->ct_lock);
  
    | 
      ↓ open down ↓ | 
    914 lines elided | 
    
      ↑ open up ↑ | 
  
 948  949                  VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
 949  950                  VERIFY(nvlist_add_uint32(nvl, CTPE_PID, p->p_pid) == 0);
 950  951                  VERIFY(nvlist_add_int32(nvl, CTPE_EXITSTATUS, exitstatus) == 0);
 951  952  
 952  953                  event = kmem_zalloc(sizeof (ct_kevent_t), KM_SLEEP);
 953  954                  event->cte_flags = EVINFOP(ctp, CT_PR_EV_EXIT) ? CTE_INFO : 0;
 954  955                  event->cte_type = CT_PR_EV_EXIT;
 955  956                  (void) cte_publish_all(ct, event, nvl, NULL);
 956  957                  mutex_enter(&ct->ct_lock);
 957  958          }
      959 +
      960 +        /*
      961 +         * CT_PR_EV_EXIT is not part of the CT_PR_ALLFATAL definition since
      962 +         * we never allow including this in the fatal set via a user-land
      963 +         * application, but we do allow CT_PR_EV_EXIT in the contract's fatal
      964 +         * set for a process setup for zone init. See zone_start_init().
      965 +         */
      966 +        if (EVFATALP(ctp, CT_PR_EV_EXIT)) {
      967 +                ASSERT(MUTEX_HELD(&ct->ct_lock));
      968 +                contract_process_kill(ct, p, B_TRUE);
      969 +        }
      970 +
 958  971          if (empty) {
 959  972                  /*
 960  973                   * Send EMPTY message.
 961  974                   */
 962  975                  if (EVSENDP(ctp, CT_PR_EV_EMPTY)) {
 963  976                          nvlist_t *nvl;
 964  977  
 965  978                          mutex_exit(&ct->ct_lock);
 966  979                          VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME,
 967  980                              KM_SLEEP) == 0);
 968  981                          VERIFY(nvlist_add_uint32(nvl, CTPE_PID, p->p_pid) == 0);
 969  982  
 970  983                          event = kmem_zalloc(sizeof (ct_kevent_t), KM_SLEEP);
 971  984                          event->cte_flags = EVINFOP(ctp, CT_PR_EV_EMPTY) ?
 972  985                              CTE_INFO : 0;
 973  986                          event->cte_type = CT_PR_EV_EMPTY;
 974  987                          (void) cte_publish_all(ct, event, nvl, NULL);
 975  988                          mutex_enter(&ct->ct_lock);
 976  989                  }
 977  990  
 978  991                  /*
 979  992                   * The last one to leave an orphaned contract turns out
 980  993                   * the lights.
 981  994                   */
 982  995                  if (ct->ct_state == CTS_ORPHAN) {
 983  996                          contract_destroy(ct);
 984  997                          return;
 985  998                  }
 986  999          }
 987 1000          mutex_exit(&ct->ct_lock);
 988 1001          contract_rele(ct);
 989 1002  }
 990 1003  
 991 1004  /*
 992 1005   * contract_process_fork
 993 1006   *
 994 1007   * Called on process fork.  If the current lwp has a active process
 995 1008   * contract template, we attempt to create a new process contract.
 996 1009   * Failure to create a process contract when required is a failure in
 997 1010   * fork so, in such an event, we return NULL.
 998 1011   *
 999 1012   * Assuming we succeeded or skipped the previous step, we add the child
1000 1013   * process to the new contract (success) or to the parent's process
1001 1014   * contract (skip).  If requested, we also send a fork event to that
1002 1015   * contract.
1003 1016   *
1004 1017   * Because contract_process_fork() may fail, and because we would
1005 1018   * prefer that process contracts not be created for processes which
1006 1019   * don't complete forking, this should be the last function called
1007 1020   * before the "all clear" point in cfork.
1008 1021   */
1009 1022  cont_process_t *
1010 1023  contract_process_fork(ctmpl_process_t *rtmpl, proc_t *cp, proc_t *pp,
1011 1024      int canfail)
1012 1025  {
1013 1026          contract_t *ct;
1014 1027          cont_process_t *ctp;
1015 1028          ct_kevent_t *event;
1016 1029          ct_template_t *tmpl;
1017 1030  
1018 1031          if (rtmpl == NULL && (tmpl = ttolwp(curthread)->lwp_ct_active[
1019 1032              process_type->ct_type_index]) != NULL)
1020 1033                  rtmpl = tmpl->ctmpl_data;
1021 1034  
1022 1035          if (rtmpl == NULL)
1023 1036                  ctp = curproc->p_ct_process;
1024 1037          else if ((ctp = contract_process_create(rtmpl, pp, canfail)) == NULL)
1025 1038                  return (NULL);
1026 1039  
1027 1040          ct = &ctp->conp_contract;
1028 1041          /*
1029 1042           * Prevent contract_process_kill() from missing forked children
1030 1043           * by failing forks by parents that have just been killed.
1031 1044           * It's not worth hoisting the ctp test since contract creation
1032 1045           * is by no means the common case.
1033 1046           */
1034 1047          mutex_enter(&ct->ct_lock);
1035 1048          mutex_enter(&pp->p_lock);
1036 1049          if (ctp == curproc->p_ct_process && (pp->p_flag & SKILLED) != 0 &&
1037 1050              canfail) {
1038 1051                  mutex_exit(&pp->p_lock);
1039 1052                  mutex_exit(&ct->ct_lock);
1040 1053                  return (NULL);
1041 1054          }
1042 1055          cp->p_ct_process = ctp;
1043 1056          mutex_exit(&pp->p_lock);
1044 1057          contract_hold(ct);
1045 1058          list_insert_head(&ctp->conp_members, cp);
1046 1059          ctp->conp_nmembers++;
1047 1060          mutex_exit(&ct->ct_lock);
1048 1061          if (EVSENDP(ctp, CT_PR_EV_FORK)) {
1049 1062                  nvlist_t *nvl;
  
    | 
      ↓ open down ↓ | 
    82 lines elided | 
    
      ↑ open up ↑ | 
  
1050 1063  
1051 1064                  VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1052 1065                  VERIFY(nvlist_add_uint32(nvl, CTPE_PID, cp->p_pid) == 0);
1053 1066                  VERIFY(nvlist_add_uint32(nvl, CTPE_PPID, pp->p_pid) == 0);
1054 1067  
1055 1068                  event = kmem_zalloc(sizeof (ct_kevent_t), KM_SLEEP);
1056 1069                  event->cte_flags = EVINFOP(ctp, CT_PR_EV_FORK) ? CTE_INFO : 0;
1057 1070                  event->cte_type = CT_PR_EV_FORK;
1058 1071                  (void) cte_publish_all(ct, event, nvl, NULL);
1059 1072          }
     1073 +
     1074 +        /*
     1075 +         * Because the CT_PR_KEEP_EXEC flag is meant to be used by applications
     1076 +         * which are not contract aware, we can assume that these applications
     1077 +         * will never explicitly abandon the child's new contract. Thus, we
     1078 +         * abandon it now.
     1079 +         */
     1080 +        if (ctp->conp_params & CT_PR_KEEP_EXEC) {
     1081 +                (void) contract_abandon(ct, pp, 1);
     1082 +        }
     1083 +
1060 1084          return (ctp);
1061 1085  }
1062 1086  
1063 1087  /*
1064 1088   * contract_process_core
1065 1089   *
1066 1090   * Called on core file generation attempts.  Generates a core event, if
1067 1091   * requested, containing the names of the process, global, and
1068 1092   * system-global ("zone") core files.  If dumping core is in the fatal
1069 1093   * event set, calls contract_process_kill().
1070 1094   */
1071 1095  void
1072 1096  contract_process_core(cont_process_t *ctp, proc_t *p, int sig,
1073 1097      const char *process, const char *global, const char *zone)
1074 1098  {
1075 1099          contract_t *ct = &ctp->conp_contract;
1076 1100  
1077 1101          if (EVSENDP(ctp, CT_PR_EV_CORE)) {
1078 1102                  ct_kevent_t *event;
1079 1103                  nvlist_t *nvl, *gnvl = NULL;
1080 1104  
1081 1105                  VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1082 1106                  VERIFY(nvlist_add_uint32(nvl, CTPE_PID, p->p_pid) == 0);
1083 1107                  VERIFY(nvlist_add_uint32(nvl, CTPE_SIGNAL, sig) == 0);
1084 1108                  if (process)
1085 1109                          VERIFY(nvlist_add_string(nvl, CTPE_PCOREFILE,
1086 1110                              (char *)process) == 0);
1087 1111                  if (global)
1088 1112                          VERIFY(nvlist_add_string(nvl, CTPE_GCOREFILE,
1089 1113                              (char *)global) == 0);
1090 1114  
1091 1115                  if (zone) {
1092 1116                          /*
1093 1117                           * Only the global zone is informed of the
1094 1118                           * local-zone generated global-zone core.
1095 1119                           */
1096 1120                          VERIFY(nvlist_alloc(&gnvl, NV_UNIQUE_NAME,
1097 1121                              KM_SLEEP) == 0);
1098 1122                          VERIFY(nvlist_add_string(gnvl, CTPE_ZCOREFILE,
1099 1123                              (char *)zone) == 0);
1100 1124                  }
1101 1125  
1102 1126                  event = kmem_zalloc(sizeof (ct_kevent_t), KM_SLEEP);
1103 1127                  event->cte_flags = EVINFOP(ctp, CT_PR_EV_CORE) ? CTE_INFO : 0;
1104 1128                  event->cte_type = CT_PR_EV_CORE;
1105 1129                  (void) cte_publish_all(ct, event, nvl, gnvl);
1106 1130          }
1107 1131  
1108 1132          if (EVFATALP(ctp, CT_PR_EV_CORE)) {
1109 1133                  mutex_enter(&ct->ct_lock);
1110 1134                  contract_process_kill(ct, p, B_TRUE);
1111 1135                  mutex_exit(&ct->ct_lock);
1112 1136          }
1113 1137  }
1114 1138  
1115 1139  /*
1116 1140   * contract_process_hwerr
1117 1141   *
1118 1142   * Called when a process is killed by an unrecoverable hardware error.
1119 1143   * Generates an hwerr event, if requested.  If hardware errors are in
1120 1144   * the fatal event set, calls contract_process_kill().
1121 1145   */
1122 1146  void
1123 1147  contract_process_hwerr(cont_process_t *ctp, proc_t *p)
1124 1148  {
1125 1149          contract_t *ct = &ctp->conp_contract;
1126 1150  
1127 1151          if (EVSENDP(ctp, CT_PR_EV_HWERR)) {
1128 1152                  ct_kevent_t *event;
1129 1153                  nvlist_t *nvl;
1130 1154  
1131 1155                  VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1132 1156                  VERIFY(nvlist_add_uint32(nvl, CTPE_PID, p->p_pid) == 0);
1133 1157  
1134 1158                  event = kmem_zalloc(sizeof (ct_kevent_t), KM_SLEEP);
1135 1159                  event->cte_flags = EVINFOP(ctp, CT_PR_EV_HWERR) ? CTE_INFO : 0;
1136 1160                  event->cte_type = CT_PR_EV_HWERR;
1137 1161                  (void) cte_publish_all(ct, event, nvl, NULL);
1138 1162          }
1139 1163  
1140 1164          if (EVFATALP(ctp, CT_PR_EV_HWERR)) {
1141 1165                  mutex_enter(&ct->ct_lock);
1142 1166                  contract_process_kill(ct, p, B_FALSE);
1143 1167                  mutex_exit(&ct->ct_lock);
1144 1168          }
1145 1169  }
1146 1170  
1147 1171  /*
1148 1172   * contract_process_sig
1149 1173   *
1150 1174   * Called when a process is killed by a signal originating from a
1151 1175   * process outside of its process contract or its process contract's
1152 1176   * holder.  Generates an signal event, if requested, containing the
1153 1177   * signal number, and the sender's pid and contract id (if available).
1154 1178   * If signals are in the fatal event set, calls
1155 1179   * contract_process_kill().
1156 1180   */
1157 1181  void
1158 1182  contract_process_sig(cont_process_t *ctp, proc_t *p, int sig, pid_t pid,
1159 1183      ctid_t ctid, zoneid_t zoneid)
1160 1184  {
1161 1185          contract_t *ct = &ctp->conp_contract;
1162 1186  
1163 1187          if (EVSENDP(ctp, CT_PR_EV_SIGNAL)) {
1164 1188                  ct_kevent_t *event;
1165 1189                  nvlist_t *dest, *nvl, *gnvl = NULL;
1166 1190  
1167 1191                  VERIFY(nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP) == 0);
1168 1192                  VERIFY(nvlist_add_uint32(nvl, CTPE_PID, p->p_pid) == 0);
1169 1193                  VERIFY(nvlist_add_uint32(nvl, CTPE_SIGNAL, sig) == 0);
1170 1194  
1171 1195                  if (zoneid >= 0 && p->p_zone->zone_id != zoneid) {
1172 1196                          VERIFY(nvlist_alloc(&gnvl, NV_UNIQUE_NAME,
1173 1197                              KM_SLEEP) == 0);
1174 1198                          dest = gnvl;
1175 1199                  } else {
1176 1200                          dest = nvl;
1177 1201                  }
1178 1202  
1179 1203                  if (pid != -1)
1180 1204                          VERIFY(nvlist_add_uint32(dest, CTPE_SENDER, pid) == 0);
1181 1205                  if (ctid != 0)
1182 1206                          VERIFY(nvlist_add_uint32(dest, CTPE_SENDCT, ctid) == 0);
1183 1207  
1184 1208                  event = kmem_zalloc(sizeof (ct_kevent_t), KM_SLEEP);
1185 1209                  event->cte_flags = EVINFOP(ctp, CT_PR_EV_SIGNAL) ? CTE_INFO : 0;
1186 1210                  event->cte_type = CT_PR_EV_SIGNAL;
1187 1211                  (void) cte_publish_all(ct, event, nvl, gnvl);
1188 1212          }
1189 1213  
1190 1214          if (EVFATALP(ctp, CT_PR_EV_SIGNAL)) {
1191 1215                  mutex_enter(&ct->ct_lock);
1192 1216                  contract_process_kill(ct, p, B_TRUE);
1193 1217                  mutex_exit(&ct->ct_lock);
1194 1218          }
1195 1219  }
  
    | 
      ↓ open down ↓ | 
    126 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX