/* * construct SetupList (policy) part of manifest structure (w/o channels) * note: malloc(). must be called only once */ void SetupUserPolicy(struct NaClApp *nap) { /* allocate space for policy */ struct SetupList *policy = malloc(sizeof(*policy)); COND_ABORT(!policy, "cannot allocate memory for user policy\n"); policy->self_size = sizeof(*policy); /* set self size */ /* setup limits */ TRANSET(policy->max_cpu, "CPUMax"); TRANSET(policy->max_mem, "MemMax"); TRANSET(policy->max_setup_calls, "SetupCallsMax"); TRANSET(policy->max_syscalls, "SyscallsMax"); /* setup counters */ policy->cnt_cpu = 0; policy->cnt_cpu_last = 0; policy->cnt_mem = 0; policy->cnt_setup_calls = 0; policy->cnt_syscalls = 0; policy->heap_ptr = 0; /* set user heap to NULL until it allocated */ /* clear syscallback */ policy->syscallback = 0; /* setup custom attributes */ #define STRNCPY_NULL(a, b, n) if ((a) && (b)) strncpy(a, b, n); STRNCPY_NULL(policy->content_type, get_value_by_key(nap, "ContentType"), CONTENT_TYPE_LEN); STRNCPY_NULL(policy->timestamp, get_value_by_key(nap, "TimeStamp"), TIMESTAMP_LEN); STRNCPY_NULL(policy->x_object_meta_tag, get_value_by_key(nap, "XObjectMetaTag"), X_OBJECT_META_TAG_LEN); STRNCPY_NULL(policy->user_etag, get_value_by_key(nap, "UserETag"), USER_TAG_LEN); #undef STRNCPY_NULL nap->manifest->user_setup = policy; }
/* * user request to change limits for system resources. for now we only can decrease bounds * return: function update given SetupList object (hint) and if there were * unsuccessful attempt to change policy return -1, otherwirse return 0 */ static int32_t TrapUserSetupHandle(struct NaClApp *nap, struct SetupList *h) { struct PreOpenedFileDesc *policy_channel; struct PreOpenedFileDesc *hint_channel; struct SetupList *policy = nap->manifest->user_setup; struct SetupList *hint = (struct SetupList*)NaClUserToSys(nap, (intptr_t) h); int32_t retcode = OK_CODE; enum ChannelType ch; /* * check/count this call. decrease number of syscalls * since this call is not really "system" */ --nap->manifest->user_setup->cnt_syscalls; if(policy->max_setup_calls < ++policy->cnt_setup_calls) return -OUT_OF_LIMITS; /* check i/o limits */ for(ch = InputChannel; ch < CHANNELS_COUNT; ++ch) { /* pick current channel settings */ policy_channel = &policy->channels[ch]; hint_channel = &hint->channels[ch]; hint_channel->self_size = policy_channel->self_size; /* set self size */ #define STRNCPY_NULL(a, b, n) if ((a) && (b)) strncpy((a), (b), (n)); #define TRY_UPDATE(pretender, current)\ do {\ if(policy->cnt_setup_calls == 1) { pretender = current; break; }\ if((pretender) < (current)) current = pretender;\ else { pretender = current; retcode = ERR_CODE; }\ } while(0) /* check/update i/o limits. 1st time - set fields in hint */ TRY_UPDATE(hint_channel->max_size, policy_channel->max_size); TRY_UPDATE(hint_channel->max_get_size, policy_channel->max_get_size); TRY_UPDATE(hint_channel->max_gets, policy_channel->max_gets); TRY_UPDATE(hint_channel->max_put_size, policy_channel->max_put_size); TRY_UPDATE(hint_channel->max_puts, policy_channel->max_puts); /* set i/o fields n/a to change */ hint_channel->bsize = policy_channel->bsize; hint_channel->buffer = policy_channel->buffer; hint_channel->fsize = policy_channel->fsize; hint_channel->type = policy_channel->type; } /* check/update system limits. 1st time - set fields in hint */ TRY_UPDATE(hint->max_cpu, policy->max_cpu); TRY_UPDATE(hint->max_mem, policy->max_mem); /* ### call unmap here? */ TRY_UPDATE(hint->max_syscalls, policy->max_syscalls); TRY_UPDATE(hint->max_setup_calls, policy->max_setup_calls); /* set system fields n/a to change */ hint->self_size = policy->self_size; /* set self size */ hint->heap_ptr = policy->heap_ptr; /* set self size */ STRNCPY_NULL(hint->content_type, policy->content_type, CONTENT_TYPE_LEN); STRNCPY_NULL(hint->timestamp, policy->timestamp, TIMESTAMP_LEN); STRNCPY_NULL(hint->user_etag, policy->user_etag, USER_TAG_LEN); STRNCPY_NULL(hint->x_object_meta_tag, policy->x_object_meta_tag, X_OBJECT_META_TAG_LEN); /* update syscallback */ if(UpdateSyscallback(nap, hint) == ERR_CODE) retcode = ERR_CODE; #undef STRNCPY_NULL #undef TRY_UPDATE return retcode; }