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


  36 #include <errno.h>
  37 #include <exec_attr.h>
  38 #include <grp.h>
  39 #include <libsysevent.h>
  40 #include <libuutil.h>
  41 #include <limits.h>
  42 #include <link.h>
  43 #include <malloc.h>
  44 #include <pool.h>
  45 #include <priv.h>
  46 #include <project.h>
  47 #include <pthread.h>
  48 #include <pwd.h>
  49 #include <secdb.h>
  50 #include <signal.h>
  51 #include <stdlib.h>
  52 #include <string.h>
  53 #include <syslog.h>
  54 #include <sys/corectl.h>
  55 #include <sys/machelf.h>

  56 #include <sys/task.h>
  57 #include <sys/types.h>
  58 #include <time.h>
  59 #include <unistd.h>
  60 #include <ucontext.h>
  61 
  62 #define min(a, b)               ((a) > (b) ? (b) : (a))
  63 
  64 #define MKW_TRUE        ":true"
  65 #define MKW_KILL        ":kill"
  66 #define MKW_KILL_PROC   ":kill_process"
  67 
  68 #define ALLOCFAIL       ((char *)"Allocation failure.")
  69 #define RCBROKEN        ((char *)"Repository connection broken.")
  70 
  71 #define MAX_COMMIT_RETRIES              10
  72 #define MAX_COMMIT_RETRY_INT            (5 * 1000000)   /* 5 seconds */
  73 #define INITIAL_COMMIT_RETRY_INT        (10000)         /* 1/100th second */
  74 
  75 /*


2826 
2827         (void) memset(cip, 0, sizeof (*cip));
2828         cip->uid = (uid_t)-1;
2829         cip->euid = (uid_t)-1;
2830         cip->gid = (gid_t)-1;
2831         cip->egid = (gid_t)-1;
2832 
2833         cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
2834         assert(cip->vbuf_sz >= 0);
2835         cip->vbuf = malloc(cip->vbuf_sz);
2836         if (cip->vbuf == NULL) {
2837                 free(cip);
2838                 return (mc_error_create(err, ENOMEM, ALLOCFAIL));
2839         }
2840 
2841         if ((instpg = scf_pg_create(h)) == NULL ||
2842             (methpg = scf_pg_create(h)) == NULL ||
2843             (prop = scf_property_create(h)) == NULL ||
2844             (val = scf_value_create(h)) == NULL) {
2845                 err = mc_error_create(err, scf_error(),
2846                     "Failed to create repository object: %s\n",
2847                     scf_strerror(scf_error()));
2848                 goto out;
2849         }
2850 
2851         /*
2852          * The method environment, and the credentials/profile data,
2853          * may be found either in the pg for the method (methpg),
2854          * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named
2855          * instpg below).
2856          */
2857 
2858         if (scf_instance_get_pg_composed(inst, snap, mname, methpg) !=
2859             SCF_SUCCESS) {
2860                 err = mc_error_create(err, scf_error(), "Unable to get the "
2861                     "\"%s\" method, %s", mname, scf_strerror(scf_error()));
2862                 goto out;
2863         }
2864 
2865         if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT,
2866             instpg) != SCF_SUCCESS) {


2878 
2879         ret = get_environment(h, methpg, cip, prop, val);
2880         if (ret == ENOENT && instpg != NULL) {
2881                 ret = get_environment(h, instpg, cip, prop, val);
2882         }
2883 
2884         switch (ret) {
2885         case 0:
2886                 mc_used++;
2887                 break;
2888         case ENOENT:
2889                 break;
2890         case ENOMEM:
2891                 err = mc_error_create(err, ret, "Out of memory.");
2892                 goto out;
2893         case EINVAL:
2894                 err = mc_error_create(err, ret, "Invalid method environment.");
2895                 goto out;
2896         default:
2897                 err = mc_error_create(err, ret,
2898                     "Get method environment failed : %s\n", scf_strerror(ret));
2899                 goto out;
2900         }
2901 
2902         pg = methpg;
2903 
2904         ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop);
2905         if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) {
2906                 pg = NULL;
2907                 ret = scf_pg_get_property(instpg, SCF_PROPERTY_USE_PROFILE,
2908                     prop);
2909         }
2910 
2911         if (ret) {
2912                 switch (scf_error()) {
2913                 case SCF_ERROR_NOT_FOUND:
2914                         /* No profile context: use default credentials */
2915                         cip->uid = 0;
2916                         cip->gid = 0;
2917                         break;
2918 


3086                             "Could not get passwd entry.");
3087                         goto out;
3088 
3089                 default:
3090                         bad_fail("lookup_pwd", ret);
3091                 }
3092 
3093                 cip->working_dir = strdup(cip->pwd.pw_dir);
3094                 if (cip->working_dir == NULL) {
3095                         err = mc_error_create(err, ENOMEM, ALLOCFAIL);
3096                         goto out;
3097                 }
3098         } else {
3099                 cip->working_dir = strdup(cip->vbuf);
3100                 if (cip->working_dir == NULL) {
3101                         err = mc_error_create(err, ENOMEM, ALLOCFAIL);
3102                         goto out;
3103                 }
3104         }
3105 



















































































3106         /* get (optional) corefile pattern */
3107         if ((methpg != NULL && scf_pg_get_property(methpg,
3108             SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) ||
3109             (instpg != NULL && scf_pg_get_property(instpg,
3110             SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS)) {
3111                 if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3112                         ret = scf_error();
3113                         switch (ret) {
3114                         case SCF_ERROR_CONNECTION_BROKEN:
3115                                 err = mc_error_create(err, ret, RCBROKEN);
3116                                 break;
3117 
3118                         case SCF_ERROR_CONSTRAINT_VIOLATED:
3119                                 err = mc_error_create(err, ret,
3120                                     "\"%s\" property has multiple values.",
3121                                     SCF_PROPERTY_COREFILE_PATTERN);
3122                                 break;
3123 
3124                         case SCF_ERROR_NOT_FOUND:
3125                                 err = mc_error_create(err, ret,


3326                                 goto out;
3327                         }
3328                 }
3329         }
3330 
3331         /*
3332          * A method_context was not used for any configurable
3333          * elements or attributes, so reset and use the simple
3334          * defaults that provide historic init behavior.
3335          */
3336         if (mc_used == 0) {
3337                 free(cip->pwbuf);
3338                 free(cip->vbuf);
3339                 free(cip->working_dir);
3340 
3341                 (void) memset(cip, 0, sizeof (*cip));
3342                 cip->uid = 0;
3343                 cip->gid = 0;
3344                 cip->euid = (uid_t)-1;
3345                 cip->egid = (gid_t)-1;













3346         }
3347 
3348         *mcpp = cip;
3349 
3350 out:
3351         (void) scf_value_destroy(val);
3352         scf_property_destroy(prop);
3353         scf_pg_destroy(instpg);
3354         scf_pg_destroy(methpg);
3355 
3356         if (cip->pwbuf != NULL) {
3357                 free(cip->pwbuf);
3358                 cip->pwbuf = NULL;
3359         }
3360 
3361         free(cip->vbuf);
3362 
3363         if (err->type != 0) {
3364                 restarter_free_method_context(cip);
3365         } else {


3398  *   EACCES - could not access working_dir (chdir)
3399  *            in a TASK_FINAL task (setproject, settaskid)
3400  *            no resource pool accepting default binding exists (setproject)
3401  *   ELOOP - too many symbolic links in working_dir (chdir)
3402  *   ENAMETOOLONG - working_dir is too long (chdir)
3403  *   ENOLINK - working_dir is on an inaccessible remote machine (chdir)
3404  *   ENOTDIR - working_dir is not a directory (chdir)
3405  *   ESRCH - uid is not a user of project (setproject)
3406  *           project is invalid (setproject)
3407  *           the resource pool specified for project is unknown (setproject)
3408  *   EBADF - the configuration for the pool is invalid (pool_set_binding)
3409  *   -1 - core_set_process_path() failed (core_set_process_path)
3410  *        a resource control assignment failed (setproject)
3411  *        a system error occurred during pool_set_binding (pool_set_binding)
3412  */
3413 int
3414 restarter_set_method_context(struct method_context *cip, const char **fp)
3415 {
3416         pid_t mypid = -1;
3417         int r, ret;

3418 
3419         cip->pwbuf = NULL;
3420         *fp = NULL;
3421 
3422         if (cip->gid != (gid_t)-1) {
3423                 if (setregid(cip->gid,
3424                     cip->egid != (gid_t)-1 ? cip->egid : cip->gid) != 0) {
3425                         *fp = "setregid";
3426 
3427                         ret = errno;
3428                         assert(ret == EINVAL || ret == EPERM);
3429                         goto out;
3430                 }
3431         } else {
3432                 if (cip->pwbuf == NULL) {
3433                         switch (ret = lookup_pwd(cip)) {
3434                         case 0:
3435                                 break;
3436 
3437                         case ENOMEM:


3493         } else if (cip->ngroups > 0 &&
3494             setgroups(cip->ngroups, cip->groups) != 0) {
3495                 *fp = "setgroups";
3496 
3497                 ret = errno;
3498                 assert(ret == EINVAL || ret == EPERM);
3499                 goto out;
3500         }
3501 
3502         if (cip->corefile_pattern != NULL) {
3503                 mypid = getpid();
3504 
3505                 if (core_set_process_path(cip->corefile_pattern,
3506                     strlen(cip->corefile_pattern) + 1, mypid) != 0) {
3507                         *fp = "core_set_process_path";
3508                         ret = -1;
3509                         goto out;
3510                 }
3511         }
3512 

































3513         if (restarter_rm_libs_loadable()) {
3514                 if (cip->project == NULL) {
3515                         if (settaskid(getprojid(), TASK_NORMAL) == -1) {
3516                                 switch (errno) {
3517                                 case EACCES:
3518                                 case EPERM:
3519                                         *fp = "settaskid";
3520                                         ret = errno;
3521                                         goto out;
3522 
3523                                 case EINVAL:
3524                                 default:
3525                                         bad_fail("settaskid", errno);
3526                                 }
3527                         }
3528                 } else {
3529                         switch (ret = lookup_pwd(cip)) {
3530                         case 0:
3531                                 break;
3532 




  36 #include <errno.h>
  37 #include <exec_attr.h>
  38 #include <grp.h>
  39 #include <libsysevent.h>
  40 #include <libuutil.h>
  41 #include <limits.h>
  42 #include <link.h>
  43 #include <malloc.h>
  44 #include <pool.h>
  45 #include <priv.h>
  46 #include <project.h>
  47 #include <pthread.h>
  48 #include <pwd.h>
  49 #include <secdb.h>
  50 #include <signal.h>
  51 #include <stdlib.h>
  52 #include <string.h>
  53 #include <syslog.h>
  54 #include <sys/corectl.h>
  55 #include <sys/machelf.h>
  56 #include <sys/secflags.h>
  57 #include <sys/task.h>
  58 #include <sys/types.h>
  59 #include <time.h>
  60 #include <unistd.h>
  61 #include <ucontext.h>
  62 
  63 #define min(a, b)               ((a) > (b) ? (b) : (a))
  64 
  65 #define MKW_TRUE        ":true"
  66 #define MKW_KILL        ":kill"
  67 #define MKW_KILL_PROC   ":kill_process"
  68 
  69 #define ALLOCFAIL       ((char *)"Allocation failure.")
  70 #define RCBROKEN        ((char *)"Repository connection broken.")
  71 
  72 #define MAX_COMMIT_RETRIES              10
  73 #define MAX_COMMIT_RETRY_INT            (5 * 1000000)   /* 5 seconds */
  74 #define INITIAL_COMMIT_RETRY_INT        (10000)         /* 1/100th second */
  75 
  76 /*


2827 
2828         (void) memset(cip, 0, sizeof (*cip));
2829         cip->uid = (uid_t)-1;
2830         cip->euid = (uid_t)-1;
2831         cip->gid = (gid_t)-1;
2832         cip->egid = (gid_t)-1;
2833 
2834         cip->vbuf_sz = scf_limit(SCF_LIMIT_MAX_VALUE_LENGTH);
2835         assert(cip->vbuf_sz >= 0);
2836         cip->vbuf = malloc(cip->vbuf_sz);
2837         if (cip->vbuf == NULL) {
2838                 free(cip);
2839                 return (mc_error_create(err, ENOMEM, ALLOCFAIL));
2840         }
2841 
2842         if ((instpg = scf_pg_create(h)) == NULL ||
2843             (methpg = scf_pg_create(h)) == NULL ||
2844             (prop = scf_property_create(h)) == NULL ||
2845             (val = scf_value_create(h)) == NULL) {
2846                 err = mc_error_create(err, scf_error(),
2847                     "Failed to create repository object: %s",
2848                     scf_strerror(scf_error()));
2849                 goto out;
2850         }
2851 
2852         /*
2853          * The method environment, and the credentials/profile data,
2854          * may be found either in the pg for the method (methpg),
2855          * or in the instance/service SCF_PG_METHOD_CONTEXT pg (named
2856          * instpg below).
2857          */
2858 
2859         if (scf_instance_get_pg_composed(inst, snap, mname, methpg) !=
2860             SCF_SUCCESS) {
2861                 err = mc_error_create(err, scf_error(), "Unable to get the "
2862                     "\"%s\" method, %s", mname, scf_strerror(scf_error()));
2863                 goto out;
2864         }
2865 
2866         if (scf_instance_get_pg_composed(inst, snap, SCF_PG_METHOD_CONTEXT,
2867             instpg) != SCF_SUCCESS) {


2879 
2880         ret = get_environment(h, methpg, cip, prop, val);
2881         if (ret == ENOENT && instpg != NULL) {
2882                 ret = get_environment(h, instpg, cip, prop, val);
2883         }
2884 
2885         switch (ret) {
2886         case 0:
2887                 mc_used++;
2888                 break;
2889         case ENOENT:
2890                 break;
2891         case ENOMEM:
2892                 err = mc_error_create(err, ret, "Out of memory.");
2893                 goto out;
2894         case EINVAL:
2895                 err = mc_error_create(err, ret, "Invalid method environment.");
2896                 goto out;
2897         default:
2898                 err = mc_error_create(err, ret,
2899                     "Get method environment failed: %s", scf_strerror(ret));
2900                 goto out;
2901         }
2902 
2903         pg = methpg;
2904 
2905         ret = scf_pg_get_property(pg, SCF_PROPERTY_USE_PROFILE, prop);
2906         if (ret && scf_error() == SCF_ERROR_NOT_FOUND && instpg != NULL) {
2907                 pg = NULL;
2908                 ret = scf_pg_get_property(instpg, SCF_PROPERTY_USE_PROFILE,
2909                     prop);
2910         }
2911 
2912         if (ret) {
2913                 switch (scf_error()) {
2914                 case SCF_ERROR_NOT_FOUND:
2915                         /* No profile context: use default credentials */
2916                         cip->uid = 0;
2917                         cip->gid = 0;
2918                         break;
2919 


3087                             "Could not get passwd entry.");
3088                         goto out;
3089 
3090                 default:
3091                         bad_fail("lookup_pwd", ret);
3092                 }
3093 
3094                 cip->working_dir = strdup(cip->pwd.pw_dir);
3095                 if (cip->working_dir == NULL) {
3096                         err = mc_error_create(err, ENOMEM, ALLOCFAIL);
3097                         goto out;
3098                 }
3099         } else {
3100                 cip->working_dir = strdup(cip->vbuf);
3101                 if (cip->working_dir == NULL) {
3102                         err = mc_error_create(err, ENOMEM, ALLOCFAIL);
3103                         goto out;
3104                 }
3105         }
3106 
3107         /* get security flags */
3108         if ((methpg != NULL && scf_pg_get_property(methpg,
3109             SCF_PROPERTY_SECFLAGS, prop) == SCF_SUCCESS) ||
3110             (instpg != NULL && scf_pg_get_property(instpg,
3111             SCF_PROPERTY_SECFLAGS, prop) == SCF_SUCCESS)) {
3112                 if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3113                         ret = scf_error();
3114                         switch (ret) {
3115                         case SCF_ERROR_CONNECTION_BROKEN:
3116                                 err = mc_error_create(err, ret, RCBROKEN);
3117                                 break;
3118 
3119                         case SCF_ERROR_CONSTRAINT_VIOLATED:
3120                                 err = mc_error_create(err, ret,
3121                                     "\"%s\" property has multiple values.",
3122                                     SCF_PROPERTY_SECFLAGS);
3123                                 break;
3124 
3125                         case SCF_ERROR_NOT_FOUND:
3126                                 err = mc_error_create(err, ret,
3127                                     "\"%s\" property has no values.",
3128                                     SCF_PROPERTY_SECFLAGS);
3129                                 break;
3130 
3131                         default:
3132                                 bad_fail("scf_property_get_value", ret);
3133                         }
3134 
3135                         (void) strlcpy(cip->vbuf, ":default", cip->vbuf_sz);
3136                 } else {
3137                         ret = scf_value_get_astring(val, cip->vbuf,
3138                             cip->vbuf_sz);
3139                         assert(ret != -1);
3140                 }
3141                 mc_used++;
3142         } else {
3143                 ret = scf_error();
3144                 switch (ret) {
3145                 case SCF_ERROR_NOT_FOUND:
3146                         /* okay if missing. */
3147                         (void) strlcpy(cip->vbuf, ":default", cip->vbuf_sz);
3148                         break;
3149 
3150                 case SCF_ERROR_CONNECTION_BROKEN:
3151                         err = mc_error_create(err, ret, RCBROKEN);
3152                         goto out;
3153 
3154                 case SCF_ERROR_DELETED:
3155                         err = mc_error_create(err, ret,
3156                             "Property group could not be found");
3157                         goto out;
3158 
3159                 case SCF_ERROR_HANDLE_MISMATCH:
3160                 case SCF_ERROR_INVALID_ARGUMENT:
3161                 case SCF_ERROR_NOT_SET:
3162                 default:
3163                         bad_fail("scf_pg_get_property", ret);
3164                 }
3165         }
3166 
3167 
3168         if (scf_default_secflags(h, &cip->def_secflags) != 0) {
3169                 err = mc_error_create(err, EINVAL, "couldn't fetch "
3170                     "default security-flags");
3171                 goto out;
3172         }
3173 
3174         if (strcmp(cip->vbuf, ":default") == 0) {
3175                 if (secflags_parse(&cip->def_secflags.psf_inherit, "default",
3176                     &cip->secflag_delta) != 0) {
3177                         err = mc_error_create(err, EINVAL, "couldn't parse "
3178                             "security flags: %s", cip->vbuf);
3179                         goto out;
3180                 }
3181         } else {
3182                 if (secflags_parse(&cip->def_secflags.psf_inherit, cip->vbuf,
3183                     &cip->secflag_delta) != 0) {
3184                         err = mc_error_create(err, EINVAL, "couldn't parse "
3185                             "security flags: %s", cip->vbuf);
3186                         goto out;
3187                 }
3188         }
3189 
3190         /* get (optional) corefile pattern */
3191         if ((methpg != NULL && scf_pg_get_property(methpg,
3192             SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS) ||
3193             (instpg != NULL && scf_pg_get_property(instpg,
3194             SCF_PROPERTY_COREFILE_PATTERN, prop) == SCF_SUCCESS)) {
3195                 if (scf_property_get_value(prop, val) != SCF_SUCCESS) {
3196                         ret = scf_error();
3197                         switch (ret) {
3198                         case SCF_ERROR_CONNECTION_BROKEN:
3199                                 err = mc_error_create(err, ret, RCBROKEN);
3200                                 break;
3201 
3202                         case SCF_ERROR_CONSTRAINT_VIOLATED:
3203                                 err = mc_error_create(err, ret,
3204                                     "\"%s\" property has multiple values.",
3205                                     SCF_PROPERTY_COREFILE_PATTERN);
3206                                 break;
3207 
3208                         case SCF_ERROR_NOT_FOUND:
3209                                 err = mc_error_create(err, ret,


3410                                 goto out;
3411                         }
3412                 }
3413         }
3414 
3415         /*
3416          * A method_context was not used for any configurable
3417          * elements or attributes, so reset and use the simple
3418          * defaults that provide historic init behavior.
3419          */
3420         if (mc_used == 0) {
3421                 free(cip->pwbuf);
3422                 free(cip->vbuf);
3423                 free(cip->working_dir);
3424 
3425                 (void) memset(cip, 0, sizeof (*cip));
3426                 cip->uid = 0;
3427                 cip->gid = 0;
3428                 cip->euid = (uid_t)-1;
3429                 cip->egid = (gid_t)-1;
3430 
3431                 if (scf_default_secflags(h, &cip->def_secflags) != 0) {
3432                         err = mc_error_create(err, EINVAL, "couldn't fetch "
3433                             "default security-flags");
3434                         goto out;
3435                 }
3436 
3437                 if (secflags_parse(&cip->def_secflags.psf_inherit, "default",
3438                     &cip->secflag_delta) != 0) {
3439                         err = mc_error_create(err, EINVAL, "couldn't parse "
3440                             "security flags: %s", cip->vbuf);
3441                         goto out;
3442                 }
3443         }
3444 
3445         *mcpp = cip;
3446 
3447 out:
3448         (void) scf_value_destroy(val);
3449         scf_property_destroy(prop);
3450         scf_pg_destroy(instpg);
3451         scf_pg_destroy(methpg);
3452 
3453         if (cip->pwbuf != NULL) {
3454                 free(cip->pwbuf);
3455                 cip->pwbuf = NULL;
3456         }
3457 
3458         free(cip->vbuf);
3459 
3460         if (err->type != 0) {
3461                 restarter_free_method_context(cip);
3462         } else {


3495  *   EACCES - could not access working_dir (chdir)
3496  *            in a TASK_FINAL task (setproject, settaskid)
3497  *            no resource pool accepting default binding exists (setproject)
3498  *   ELOOP - too many symbolic links in working_dir (chdir)
3499  *   ENAMETOOLONG - working_dir is too long (chdir)
3500  *   ENOLINK - working_dir is on an inaccessible remote machine (chdir)
3501  *   ENOTDIR - working_dir is not a directory (chdir)
3502  *   ESRCH - uid is not a user of project (setproject)
3503  *           project is invalid (setproject)
3504  *           the resource pool specified for project is unknown (setproject)
3505  *   EBADF - the configuration for the pool is invalid (pool_set_binding)
3506  *   -1 - core_set_process_path() failed (core_set_process_path)
3507  *        a resource control assignment failed (setproject)
3508  *        a system error occurred during pool_set_binding (pool_set_binding)
3509  */
3510 int
3511 restarter_set_method_context(struct method_context *cip, const char **fp)
3512 {
3513         pid_t mypid = -1;
3514         int r, ret;
3515         secflagdelta_t delta = {0};
3516 
3517         cip->pwbuf = NULL;
3518         *fp = NULL;
3519 
3520         if (cip->gid != (gid_t)-1) {
3521                 if (setregid(cip->gid,
3522                     cip->egid != (gid_t)-1 ? cip->egid : cip->gid) != 0) {
3523                         *fp = "setregid";
3524 
3525                         ret = errno;
3526                         assert(ret == EINVAL || ret == EPERM);
3527                         goto out;
3528                 }
3529         } else {
3530                 if (cip->pwbuf == NULL) {
3531                         switch (ret = lookup_pwd(cip)) {
3532                         case 0:
3533                                 break;
3534 
3535                         case ENOMEM:


3591         } else if (cip->ngroups > 0 &&
3592             setgroups(cip->ngroups, cip->groups) != 0) {
3593                 *fp = "setgroups";
3594 
3595                 ret = errno;
3596                 assert(ret == EINVAL || ret == EPERM);
3597                 goto out;
3598         }
3599 
3600         if (cip->corefile_pattern != NULL) {
3601                 mypid = getpid();
3602 
3603                 if (core_set_process_path(cip->corefile_pattern,
3604                     strlen(cip->corefile_pattern) + 1, mypid) != 0) {
3605                         *fp = "core_set_process_path";
3606                         ret = -1;
3607                         goto out;
3608                 }
3609         }
3610 
3611 
3612         delta.psd_ass_active = B_TRUE;
3613         secflags_copy(&delta.psd_assign, &cip->def_secflags.psf_inherit);
3614         if (psecflags(P_PID, P_MYID, PSF_INHERIT,
3615             &delta) != 0) {
3616                 *fp = "psecflags (inherit defaults)";
3617                 ret = errno;
3618                 goto out;
3619         }
3620 
3621         if (psecflags(P_PID, P_MYID, PSF_INHERIT,
3622             &cip->secflag_delta) != 0) {
3623                 *fp = "psecflags (inherit)";
3624                 ret = errno;
3625                 goto out;
3626         }
3627 
3628         secflags_copy(&delta.psd_assign, &cip->def_secflags.psf_lower);
3629         if (psecflags(P_PID, P_MYID, PSF_LOWER,
3630             &delta) != 0) {
3631                 *fp = "psecflags (lower)";
3632                 ret = errno;
3633                 goto out;
3634         }
3635 
3636         secflags_copy(&delta.psd_assign, &cip->def_secflags.psf_upper);
3637         if (psecflags(P_PID, P_MYID, PSF_UPPER,
3638             &delta) != 0) {
3639                 *fp = "psecflags (upper)";
3640                 ret = errno;
3641                 goto out;
3642         }
3643 
3644         if (restarter_rm_libs_loadable()) {
3645                 if (cip->project == NULL) {
3646                         if (settaskid(getprojid(), TASK_NORMAL) == -1) {
3647                                 switch (errno) {
3648                                 case EACCES:
3649                                 case EPERM:
3650                                         *fp = "settaskid";
3651                                         ret = errno;
3652                                         goto out;
3653 
3654                                 case EINVAL:
3655                                 default:
3656                                         bad_fail("settaskid", errno);
3657                                 }
3658                         }
3659                 } else {
3660                         switch (ret = lookup_pwd(cip)) {
3661                         case 0:
3662                                 break;
3663