Projects
Browse Source     Search     Timeline     Wiki

Changeset 23264

Show
Ignore:
Timestamp:
05/25/07 13:44:01 (19 months ago)
Author:
zarzycki@…
Message:

<rdar://problem/4991686> spawn_via_launchd: specify quarantine and seatbelt information

Location:
trunk/launchd/src
Files:
6 modified

Legend:

Unmodified
Added
Removed
  • trunk/launchd/src/launchd_core_logic.c

    r23262 r23264  
    7373#include <glob.h> 
    7474#include <spawn.h> 
     75#include <sandbox.h> 
    7576 
    7677#include "liblaunch_public.h" 
     
    195196static void limititem_delete(job_t j, struct limititem *li); 
    196197static void limititem_setup(launch_data_t obj, const char *key, void *context); 
     198static void seatbelt_setup_flags(launch_data_t obj, const char *key, void *context); 
    197199 
    198200typedef enum { 
     
    298300        struct rusage ru; 
    299301#endif 
    300         binpref_t j_binpref; 
     302        cpu_type_t *j_binpref; 
    301303        size_t j_binpref_cnt; 
    302304        mach_port_t j_port; 
     
    314316        struct machservice *lastlookup; 
    315317        unsigned int lastlookup_gennum; 
     318        char *seatbelt_profile; 
     319        uint64_t seatbelt_flags; 
     320        void *quarantine_data; 
     321        size_t quarantine_data_sz; 
    316322        pid_t p; 
    317323        int argc; 
     
    355361static void job_import_dictionary(job_t j, const char *key, launch_data_t value); 
    356362static void job_import_array(job_t j, const char *key, launch_data_t value); 
     363static void job_import_opaque(job_t j, const char *key, launch_data_t value); 
    357364static bool job_set_global_on_demand(job_t j, bool val); 
    358365static void job_watch(job_t j); 
     
    377384static job_t job_new_anonymous(jobmgr_t jm, pid_t anonpid); 
    378385static job_t job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv); 
    379 static job_t job_new_spawn(job_t j, const char *label, const char *path, const char *workingdir, const char *const *argv, const char *const *env, mode_t *u_mask, bool w4d); 
    380386static job_t job_new_via_mach_init(job_t j, const char *cmd, uid_t uid, bool ond); 
    381387static const char *job_prog(job_t j); 
     
    774780                free(j->stderrpath); 
    775781        } 
     782        if (j->seatbelt_profile) { 
     783                free(j->seatbelt_profile); 
     784        } 
     785        if (j->quarantine_data) { 
     786                free(j->quarantine_data); 
     787        } 
    776788        if (j->start_interval) { 
    777789                job_assumes(j, kevent_mod((uintptr_t)&j->start_interval, EVFILT_TIMER, EV_DELETE, 0, 0, NULL) != -1); 
     
    920932 
    921933        return 0; 
    922 } 
    923  
    924 job_t  
    925 job_new_spawn(job_t j, const char *label, const char *path, const char *workingdir, const char *const *argv, const char *const *env, mode_t *u_mask, bool w4d) 
    926 { 
    927         job_t jr; 
    928         size_t i; 
    929  
    930         if ((jr = job_find(label)) != NULL) { 
    931                 errno = EEXIST; 
    932                 return NULL; 
    933         } 
    934  
    935         jr = job_new(j->mgr, label, path, argv); 
    936  
    937         if (!jr) { 
    938                 return NULL; 
    939         } 
    940  
    941         job_reparent_hack(jr, NULL); 
    942  
    943         if (getpid() == 1) { 
    944                 struct ldcred ldc; 
    945  
    946                 runtime_get_caller_creds(&ldc); 
    947                 jr->mach_uid = ldc.uid; 
    948         } 
    949  
    950         jr->unload_at_exit = true; 
    951         jr->wait4pipe_eof = true; 
    952         jr->stall_before_exec = w4d; 
    953  
    954         if (workingdir) { 
    955                 jr->workingdir = strdup(workingdir); 
    956         } 
    957  
    958         if (u_mask) { 
    959                 jr->mask = *u_mask; 
    960                 jr->setmask = true; 
    961         } 
    962  
    963         if (env) for (i = 0; env[i]; i++) { 
    964                 char *eqoff, tmpstr[strlen(env[i]) + 1]; 
    965  
    966                 strcpy(tmpstr, env[i]); 
    967  
    968                 eqoff = strchr(tmpstr, '='); 
    969  
    970                 if (!eqoff) { 
    971                         job_log(jr, LOG_WARNING, "Environmental variable missing '=' separator: %s", tmpstr); 
    972                         continue; 
    973                 } 
    974  
    975                 *eqoff = '\0'; 
    976                 envitem_new(jr, tmpstr, eqoff + 1, false); 
    977         } 
    978  
    979         return jr; 
    980934} 
    981935 
     
    13581312                } else if (strcasecmp(key, LAUNCH_JOBKEY_STANDARDERRORPATH) == 0) { 
    13591313                        where2put = &j->stderrpath; 
     1314                } else if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOXPROFILE) == 0) { 
     1315                        where2put = &j->seatbelt_profile; 
    13601316                } 
    13611317                break; 
     
    14271383                                job_log_error(j, LOG_ERR, "adding kevent timer"); 
    14281384                        } 
    1429                 } 
     1385                } else if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOXFLAGS) == 0) { 
     1386                        j->seatbelt_flags = value; 
     1387                } 
     1388 
    14301389                break; 
    14311390        default: 
    14321391                job_log(j, LOG_WARNING, "Unknown key for integer: %s", key); 
     1392                break; 
     1393        } 
     1394} 
     1395 
     1396void 
     1397job_import_opaque(job_t j, const char *key, launch_data_t value) 
     1398{ 
     1399        switch (key[0]) { 
     1400        case 'q': 
     1401        case 'Q': 
     1402                if (strcasecmp(key, LAUNCH_JOBKEY_QUARANTINEDATA) == 0) { 
     1403                        size_t tmpsz = launch_data_get_opaque_size(value); 
     1404 
     1405                        if (job_assumes(j, j->quarantine_data = malloc(tmpsz))) { 
     1406                                memcpy(j->quarantine_data, launch_data_get_opaque(value), tmpsz); 
     1407                                j->quarantine_data_sz = tmpsz; 
     1408                        } 
     1409                } 
     1410                break; 
     1411        default: 
    14331412                break; 
    14341413        } 
     
    14781457                } else if (strcasecmp(key, LAUNCH_JOBKEY_SOFTRESOURCELIMITS) == 0) { 
    14791458                        launch_data_dict_iterate(value, limititem_setup, j); 
     1459                } else if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOXFLAGS) == 0) { 
     1460                        launch_data_dict_iterate(value, seatbelt_setup_flags, j); 
    14801461                } 
    14811462                break; 
     
    15531534                if (strcasecmp(key, LAUNCH_JOBKEY_BONJOURFDS) == 0) { 
    15541535                        socketgroup_setup(value, LAUNCH_JOBKEY_BONJOURFDS, j); 
     1536                } else if (strcasecmp(key, LAUNCH_JOBKEY_BINARYORDERPREFERENCE) == 0) { 
     1537                        if (job_assumes(j, j->j_binpref = malloc(value_cnt * sizeof(*j->j_binpref)))) { 
     1538                                j->j_binpref_cnt = value_cnt; 
     1539                                for (i = 0; i < value_cnt; i++) { 
     1540                                        j->j_binpref[i] = launch_data_get_integer(launch_data_array_get_index(value, i)); 
     1541                                } 
     1542                        } 
    15551543                } 
    15561544                break; 
     
    15961584        case LAUNCH_DATA_ARRAY: 
    15971585                job_import_array(j, key, obj); 
     1586                break; 
     1587        case LAUNCH_DATA_OPAQUE: 
     1588                job_import_opaque(j, key, obj); 
    15981589                break; 
    15991590        default: 
     
    23752366        } 
    23762367 
     2368        if (j->quarantine_data) { 
     2369                qtn_proc_t qp; 
     2370 
     2371                if (job_assumes(j, qp = qtn_proc_alloc())) { 
     2372                        if (job_assumes(j, qtn_proc_init_with_data(qp, j->quarantine_data, j->quarantine_data_sz) == 0)) { 
     2373                                job_assumes(j, qtn_proc_apply_to_self(qp) == 0); 
     2374                        } 
     2375                } 
     2376        } 
     2377 
     2378        if (j->seatbelt_profile) { 
     2379                char *seatbelt_err_buf = NULL; 
     2380 
     2381                if (!job_assumes(j, sandbox_init(j->seatbelt_profile, j->seatbelt_flags, &seatbelt_err_buf) != -1)) { 
     2382                        if (seatbelt_err_buf) { 
     2383                                job_log(j, LOG_ERR, "Sandbox failed to init: %s", seatbelt_err_buf); 
     2384                        } 
     2385                        goto out_bad; 
     2386                } 
     2387        } 
     2388 
    23772389        if (j->prog) { 
    23782390                errno = posix_spawn(&junk_pid, j->inetcompat ? file2exec : j->prog, NULL, &spattr, (char *const*)argv, environ); 
     
    23832395        } 
    23842396 
     2397out_bad: 
    23852398        _exit(EXIT_FAILURE); 
    23862399} 
     
    32293242 
    32303243        free(li); 
     3244} 
     3245 
     3246void 
     3247seatbelt_setup_flags(launch_data_t obj, const char *key, void *context) 
     3248{ 
     3249        job_t j = context; 
     3250 
     3251        if (launch_data_get_type(obj) != LAUNCH_DATA_BOOL) { 
     3252                job_log(j, LOG_WARNING, "Sandbox flag value must be boolean: %s", key); 
     3253                return; 
     3254        } 
     3255 
     3256        if (launch_data_get_bool(obj) == false) { 
     3257                return; 
     3258        } 
     3259 
     3260        if (strcasecmp(key, LAUNCH_JOBKEY_SANDBOX_NAMED) == 0) { 
     3261                j->seatbelt_flags |= SANDBOX_NAMED; 
     3262        } 
    32313263} 
    32323264 
     
    53215353        kr = _vproc_grab_subset(target_subset, &reqport, &rcvright, &out_obj_array, &l2l_ports, &l2l_port_cnt); 
    53225354 
    5323         job_log(j, LOG_NOTICE, "@@@@@ kr == 0x%x", kr); 
    5324  
    53255355        if (!job_assumes(j, kr == 0)) { 
    53265356                goto out; 
     
    53445374                job_assumes(j, obj_at_idx = launch_data_array_get_index(out_obj_array, l2l_i)); 
    53455375                job_assumes(j, tmp = launch_data_dict_lookup(obj_at_idx, TAKE_SUBSET_PID)); 
    5346                 job_assumes(j, target_pid = launch_data_get_integer(tmp)); 
     5376                target_pid = launch_data_get_integer(tmp); 
    53475377                job_assumes(j, tmp = launch_data_dict_lookup(obj_at_idx, TAKE_SUBSET_PERPID)); 
    5348                 job_assumes(j, serv_perpid = launch_data_get_bool(tmp)); 
     5378                serv_perpid = launch_data_get_bool(tmp); 
    53495379                job_assumes(j, tmp = launch_data_dict_lookup(obj_at_idx, TAKE_SUBSET_NAME)); 
    5350                 job_assumes(j, serv_name = launch_data_get_string(tmp)); 
     5380                serv_name = launch_data_get_string(tmp); 
    53515381 
    53525382                j_for_service = jobmgr_find_by_pid(jmr, target_pid, true); 
     
    56485678 
    56495679kern_return_t 
    5650 job_mig_spawn(job_t j, _internal_string_t charbuf, mach_msg_type_number_t charbuf_cnt, 
    5651                 uint32_t argc, uint32_t envc, uint64_t flags, uint16_t mig_umask, 
    5652                 binpref_t bin_pref, uint32_t binpref_cnt, pid_t *child_pid, mach_port_t *obsvr_port) 
    5653 { 
     5680job_mig_spawn(job_t j, vm_offset_t indata, mach_msg_type_number_t indataCnt, pid_t *child_pid, mach_port_t *obsvr_port) 
     5681{ 
     5682        launch_data_t input_obj = NULL; 
     5683        size_t data_offset = 0; 
     5684        struct ldcred ldc; 
    56545685        job_t jr; 
    5655         size_t offset = 0; 
    5656         char *tmpp; 
    5657         const char **argv = NULL, **env = NULL; 
    5658         const char *label = NULL; 
    5659         const char *path = NULL; 
    5660         const char *workingdir = NULL; 
    5661         size_t argv_i = 0, env_i = 0; 
    5662         struct ldcred ldc; 
    56635686 
    56645687        runtime_get_caller_creds(&ldc); 
     
    56735696        } 
    56745697 
    5675         argv = alloca((argc + 1) * sizeof(char *)); 
    5676         memset(argv, 0, (argc + 1) * sizeof(char *)); 
    5677  
    5678         if (envc > 0) { 
    5679                 env = alloca((envc + 1) * sizeof(char *)); 
    5680                 memset(env, 0, (envc + 1) * sizeof(char *)); 
    5681         } 
    5682  
    5683         while (offset < charbuf_cnt) { 
    5684                 tmpp = charbuf + offset; 
    5685                 offset += strlen(tmpp) + 1; 
    5686                 if (!label) { 
    5687                         label = tmpp; 
    5688                 } else if (argc > 0) { 
    5689                         argv[argv_i] = tmpp; 
    5690                         argv_i++; 
    5691                         argc--; 
    5692                 } else if (envc > 0) { 
    5693                         env[env_i] = tmpp; 
    5694                         env_i++; 
    5695                         envc--; 
    5696                 } else if (flags & SPAWN_HAS_PATH) { 
    5697                         path = tmpp; 
    5698                         flags &= ~SPAWN_HAS_PATH; 
    5699                 } else if (flags & SPAWN_HAS_WDIR) { 
    5700                         workingdir = tmpp; 
    5701                         flags &= ~SPAWN_HAS_WDIR; 
    5702                 } 
    5703         } 
    5704  
    5705         jr = job_new_spawn(j, label, path, workingdir, argv, env, flags & SPAWN_HAS_UMASK ? &mig_umask : NULL, 
    5706                         flags & SPAWN_WANTS_WAIT4DEBUGGER); 
     5698        if (indataCnt == 0) { 
     5699                return 1; 
     5700        } 
     5701 
     5702        if (!job_assumes(j, (input_obj = launch_data_unpack((void *)indata, indataCnt, NULL, 0, &data_offset, NULL)) != NULL)) { 
     5703                return 1; 
     5704        } 
     5705 
     5706        jr = job_import2(input_obj); 
    57075707 
    57085708        if (jr == NULL) switch (errno) { 
     
    57135713        } 
    57145714 
    5715         memcpy(jr->j_binpref, bin_pref, sizeof(jr->j_binpref)); 
    5716         jr->j_binpref_cnt = binpref_cnt; 
     5715        job_reparent_hack(jr, NULL); 
     5716 
     5717        if (getpid() == 1) { 
     5718                jr->mach_uid = ldc.uid; 
     5719        } 
     5720 
     5721        jr->unload_at_exit = true; 
     5722        jr->wait4pipe_eof = true; 
     5723        jr->stall_before_exec = jr->wait4debugger; 
     5724        jr->wait4debugger = false; 
    57175725 
    57185726        jr = job_dispatch(jr, true); 
     
    57275735        } 
    57285736 
    5729         job_log(j, LOG_INFO, "Spawned with flags:%s", flags & SPAWN_WANTS_WAIT4DEBUGGER ? " stopped": ""); 
     5737        job_log(j, LOG_INFO, "Spawned"); 
    57305738 
    57315739        *child_pid = job_get_pid(jr); 
    57325740        *obsvr_port = jr->j_port; 
    57335741 
    5734         mig_deallocate((vm_address_t)charbuf, charbuf_cnt); 
     5742        mig_deallocate(indata, indataCnt); 
    57355743 
    57365744        return BOOTSTRAP_SUCCESS; 
  • trunk/launchd/src/launchd_mig_types.defs

    r23161 r23264  
    3131type logmsg_t                   = c_string[*:2048]; 
    3232type cmd_t                      = c_string[512]; 
    33 type cmd_array_t                = ^array [] of cmd_t; 
    3433type name_t                     = c_string[128]; 
    3534type name_array_t               = ^array [] of name_t; 
    36 type _internal_string_t         = ^array [] of char; 
    3735type bootstrap_status_t         = integer_t; 
    3836type bootstrap_status_array_t   = ^array [] of bootstrap_status_t; 
    39 type binpref_t                  = array [8] of integer_t; 
    4037 
    4138type job_t = mach_port_t 
  • trunk/launchd/src/liblaunch_private.h

    r23252 r23264  
    2525#include <launch.h> 
    2626#include <unistd.h> 
     27#include <quarantine.h> 
    2728 
    2829#pragma GCC visibility push(default) 
     
    4647#define LAUNCH_KEY_BATCHQUERY           "BatchQuery" 
    4748 
     49#define LAUNCH_JOBKEY_QUARANTINEDATA    "QuarantineData" 
     50#define LAUNCH_JOBKEY_SANDBOXPROFILE    "SandboxProfile" 
     51#define LAUNCH_JOBKEY_SANDBOXFLAGS      "SandboxFlags" 
     52#define LAUNCH_JOBKEY_SANDBOX_NAMED     "Named" 
     53 
    4854#define LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL     "EnterKernelDebuggerBeforeKill" 
    4955#define LAUNCH_JOBKEY_PERJOBMACHSERVICES        "PerJobMachServices" 
    5056#define LAUNCH_JOBKEY_SERVICEIPC                "ServiceIPC" 
     57#define LAUNCH_JOBKEY_BINARYORDERPREFERENCE     "BinaryOrderPreference" 
    5158 
    5259#define LAUNCH_JOBKEY_MACH_KUNCSERVER   "kUNCServer" 
     
    107114        const cpu_type_t *      spawn_binpref; 
    108115        size_t                  spawn_binpref_cnt; 
     116        const qtn_proc_t        spawn_quarantine; 
     117        const char *            spawn_seatbelt_profile; 
     118        const uint64_t *        spawn_seatbelt_flags; 
    109119}; 
    110120 
    111 #define spawn_via_launchd(a, b, c) _spawn_via_launchd(a, b, c, 1) 
     121#define spawn_via_launchd(a, b, c) _spawn_via_launchd(a, b, c, 2) 
    112122pid_t _spawn_via_launchd( 
    113123                const char *label, 
  • trunk/launchd/src/libvproc.c

    r23262 r23264  
    173173_spawn_via_launchd(const char *label, const char *const *argv, const struct spawn_via_launchd_attr *spawn_attrs, int struct_version) 
    174174{ 
    175         kern_return_t kr; 
     175        size_t i, good_enough_size = 10*1024*1024; 
     176        mach_msg_type_number_t indata_cnt = 0; 
     177        vm_offset_t indata = 0; 
     178        mach_port_t obsvr_port = MACH_PORT_NULL; 
     179        launch_data_t tmp, tmp_array, in_obj; 
    176180        const char *const *tmpp; 
    177         size_t len, buf_len = strlen(label) + 1; 
    178         char *buf = strdup(label); 
    179         uint64_t flags = 0; 
    180         uint32_t argc = 0; 
    181         uint32_t envc = 0; 
    182         binpref_t bin_pref; 
    183         size_t binpref_cnt = 0, binpref_max = sizeof(bin_pref) / sizeof(bin_pref[0]); 
     181        kern_return_t kr = 1; 
     182        void *buf = NULL; 
    184183        pid_t p = -1; 
    185         mode_t u_mask = CMASK; 
    186         mach_port_t obsvr_port = MACH_PORT_NULL; 
    187  
    188         memset(&bin_pref, 0, sizeof(bin_pref)); 
    189  
    190         for (tmpp = argv; *tmpp; tmpp++) { 
    191                 argc++; 
    192                 len = strlen(*tmpp) + 1; 
    193                 buf = reallocf(buf, buf_len + len); 
    194                 strcpy(buf + buf_len, *tmpp); 
    195                 buf_len += len; 
    196         } 
     184 
     185        if ((in_obj = launch_data_alloc(LAUNCH_DATA_DICTIONARY)) == NULL) { 
     186                goto out; 
     187        } 
     188 
     189        if ((tmp = launch_data_new_string(label)) == NULL) { 
     190                goto out; 
     191        } 
     192 
     193        launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_LABEL); 
     194 
     195        if ((tmp_array = launch_data_alloc(LAUNCH_DATA_ARRAY)) == NULL) { 
     196                goto out; 
     197        } 
     198 
     199        for (i = 0; *argv; i++, argv++) { 
     200                tmp = launch_data_new_string(*argv); 
     201                if (tmp == NULL) { 
     202                        goto out; 
     203                } 
     204 
     205                launch_data_array_set_index(tmp_array, tmp, i); 
     206        } 
     207 
     208        launch_data_dict_insert(in_obj, tmp_array, LAUNCH_JOBKEY_PROGRAMARGUMENTS); 
    197209 
    198210        if (spawn_attrs) switch (struct_version) { 
     211        case 2: 
     212                if (spawn_attrs->spawn_quarantine) { 
     213                        char qbuf[QTN_SERIALIZED_DATA_MAX]; 
     214                        size_t qbuf_sz = QTN_SERIALIZED_DATA_MAX; 
     215 
     216                        if (qtn_proc_to_data(spawn_attrs->spawn_quarantine, qbuf, &qbuf_sz) == 0) { 
     217                                tmp = launch_data_new_opaque(qbuf, qbuf_sz); 
     218                                launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_QUARANTINEDATA); 
     219                        } 
     220                } 
     221 
     222                if (spawn_attrs->spawn_seatbelt_profile) { 
     223                        tmp = launch_data_new_string(spawn_attrs->spawn_seatbelt_profile); 
     224                        launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_SANDBOXPROFILE); 
     225                } 
     226 
     227                if (spawn_attrs->spawn_seatbelt_flags) { 
     228                        tmp = launch_data_new_integer(*spawn_attrs->spawn_seatbelt_flags); 
     229                        launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_SANDBOXFLAGS); 
     230                } 
     231 
     232                /* fall through */ 
    199233        case 1: 
    200234                if (spawn_attrs->spawn_binpref) { 
    201                         if (spawn_attrs->spawn_binpref_cnt < binpref_max) { 
    202                                 binpref_max = spawn_attrs->spawn_binpref_cnt; 
     235                        tmp_array = launch_data_alloc(LAUNCH_DATA_ARRAY); 
     236                        for (i = 0; i < spawn_attrs->spawn_binpref_cnt; i++) { 
     237                                tmp = launch_data_new_integer(spawn_attrs->spawn_binpref[i]); 
     238                                launch_data_array_set_index(tmp_array, tmp, i); 
    203239                        } 
    204  
    205                         for (; binpref_cnt < binpref_max; binpref_cnt++) { 
    206                                 bin_pref[binpref_cnt] = spawn_attrs->spawn_binpref[binpref_cnt]; 
    207                         } 
    208                 } 
    209  
     240                        launch_data_dict_insert(in_obj, tmp_array, LAUNCH_JOBKEY_BINARYORDERPREFERENCE); 
     241                } 
     242                /* fall through */ 
    210243        case 0: 
    211244                if (spawn_attrs->spawn_flags & SPAWN_VIA_LAUNCHD_STOPPED) { 
    212                         flags |= SPAWN_WANTS_WAIT4DEBUGGER; 
     245                        tmp = launch_data_new_bool(true); 
     246                        launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_WAITFORDEBUGGER); 
    213247                } 
    214248 
    215249                if (spawn_attrs->spawn_env) { 
     250                        launch_data_t tmp_dict = launch_data_alloc(LAUNCH_DATA_DICTIONARY); 
     251 
    216252                        for (tmpp = spawn_attrs->spawn_env; *tmpp; tmpp++) { 
    217                                 envc++; 
    218                                 len = strlen(*tmpp) + 1; 
    219                                 buf = reallocf(buf, buf_len + len); 
    220                                 strcpy(buf + buf_len, *tmpp); 
    221                                 buf_len += len; 
     253                                char *eqoff, tmpstr[strlen(*tmpp) + 1]; 
     254 
     255                                strcpy(tmpstr, *tmpp); 
     256 
     257                                eqoff = strchr(tmpstr, '='); 
     258 
     259                                if (!eqoff) { 
     260                                        goto out; 
     261                                } 
     262                                 
     263                                *eqoff = '\0'; 
     264                                 
     265                                launch_data_dict_insert(tmp_dict, launch_data_new_string(eqoff + 1), tmpstr); 
    222266                        } 
     267 
     268                        launch_data_dict_insert(in_obj, tmp_dict, LAUNCH_JOBKEY_ENVIRONMENTVARIABLES); 
    223269                } 
    224270 
    225271                if (spawn_attrs->spawn_path) { 
    226                         flags |= SPAWN_HAS_PATH; 
    227                         len = strlen(spawn_attrs->spawn_path) + 1; 
    228                         buf = reallocf(buf, buf_len + len); 
    229                         strcpy(buf + buf_len, spawn_attrs->spawn_path); 
    230                         buf_len += len; 
     272                        tmp = launch_data_new_string(spawn_attrs->spawn_path); 
     273                        launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_PROGRAM); 
    231274                } 
    232275 
    233276                if (spawn_attrs->spawn_chdir) { 
    234                         flags |= SPAWN_HAS_WDIR; 
    235                         len = strlen(spawn_attrs->spawn_chdir) + 1; 
    236                         buf = reallocf(buf, buf_len + len); 
    237                         strcpy(buf + buf_len, spawn_attrs->spawn_chdir); 
    238                         buf_len += len; 
     277                        tmp = launch_data_new_string(spawn_attrs->spawn_chdir); 
     278                        launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_WORKINGDIRECTORY); 
    239279                } 
    240280 
    241281                if (spawn_attrs->spawn_umask) { 
    242                         flags |= SPAWN_HAS_UMASK; 
    243                         u_mask = *spawn_attrs->spawn_umask; 
     282                        tmp = launch_data_new_integer(*spawn_attrs->spawn_umask); 
     283                        launch_data_dict_insert(in_obj, tmp, LAUNCH_JOBKEY_UMASK); 
    244284                } 
    245285 
     
    249289        } 
    250290 
    251         kr = vproc_mig_spawn(bootstrap_port, buf, buf_len, argc, envc, flags, u_mask, bin_pref, binpref_cnt, &p, &obsvr_port); 
     291        if (!(buf = malloc(good_enough_size))) { 
     292                goto out; 
     293        } 
     294 
     295