All of lore.kernel.org
 help / color / mirror / Atom feed
* A few questions about module compile/link source code
@ 2011-05-12  9:58 HarryCiao
  2011-05-20  1:13 ` Joshua Brindle
  0 siblings, 1 reply; 4+ messages in thread
From: HarryCiao @ 2011-05-12  9:58 UTC (permalink / raw)
  To: method, selinux-mailing-list

[-- Attachment #1: Type: text/plain, Size: 6896 bytes --]


Hi Joshua,

When I am studying the source code about SELinux module compile/link/expansion, so far I run into below 6 questions and would like to ask you about. I believe most of them are silly and I really appreciate you taking time to have a look at them. Or you could point me at some relevant email threads or articles or anything and I could start from there myself. Thanks !!


1, In is_id_in_scope(), if no scope_datum_t is found in the current module, then return 1 as success:

int is_id_in_scope(uint32_t symbol_type, hashtab_key_t id)
{
    scope_datum_t *scope =
        (scope_datum_t *) hashtab_search(policydbp->scope[symbol_type].
                         table, id);
    if (scope == NULL) {
        return 1;    /* id is not known, so return success */
    }
    return is_scope_in_stack(scope, stack_top);
}

Any module, either to define an identifier, or declare it as an outside dependency. Both declare_symbol() and require_symbol() would invoke symtab_insert() to register the identifier's (key, scope_datum_t) pair into the relevant scope[] hashtab, so no scope_datum_t is found would mean that the identifier is neither defined nor declared ever before, then why to return 1 as success ?


2, In define_type(), we get the attribute from the p_types hashtab for the current module:

        attr = hashtab_search(policydbp->p_types.table, id);
        if (!attr) {
            /* treat it as a fatal error */
            yyerror2("attribute %s is not declared", id);
            return -1;
        }

        if (attr->flavor != TYPE_ATTRIB) {
            yyerror2("%s is a type, not an attribute", id);
        
                if ((attr = get_local_type(id, attr->s.value, 1)) == NULL) { 
                        yyerror("Out of memory!"); 
                        return -1; 
                } 

But in get_local_type(), if the current block/decl is not global/unconditional block, then the attribute's type_datum_t would be duplicated to the current block/decl's symtab[SYM_TYPES], resulting that the current type identifier would be recorded into type_datum_t.types in the current block/decl's symtab[SYM_TYPES], rather than the one in the p_types hashtab.

Why would we need to get the local attribute from current block/decl's symtab then set its ebitmap, rather than setting the ebitmap for the one in p_types ?


3, Who decides the value for the "pass" argument to all those parser functions? how and when the value for pass is determined?

Say in define_attrib(), when pass == 1, the token in id_queue is parsed but when pass == 2, the id_queue is purged:

int define_attrib(void)
{
    if (pass == 2) {
        free(queue_remove(id_queue));
        return 0;
    }

    if (declare_type(TRUE, TRUE) == NULL) {
        return -1;
    }
    return 0;
}

But in define_te_avtab(), the id_queue is purged when pass == 1:

int define_te_avtab(int which) 
{ 
        char *id; 
        avrule_t *avrule; 
        int i; 

        if (pass == 1) { 
                for (i = 0; i < 4; i++) { 
                        while ((id = queue_remove(id_queue))) 
                                free(id); 
                } 
                return 0; 
        } 


By whom/when/how is "pass" set to be 1 or 2 ?


4, In define_te_avtab_helper(), if the current permission is not defined for a class, then "continue" to the next loop to handle the next class (to get the current permission's policy value defined in the class, record it in the  class_perm_node_t.data for that class) :

        while ((id = queue_remove(id_queue))) { 
                cur_perms = perms; 
                ebitmap_for_each_bit(&tclasses, node, i) { 
                        if (!ebitmap_node_get_bit(node, i)) 
                                continue; 
                        cladatum = policydbp->class_val_to_struct[i]; 

            ......

                        if (!perdatum) { 
                                if (!suppress) 
                                        yyerror2("permission %s is not defined for class %s", id, 
                                             policydbp->p_class_val_to_name[i]); 
                                continue;             
                        } else if (!is_perm_in_scope(id, policydbp->p_class_val_to_name[i])) { 
                                if (!suppress) { 
                                        yyerror2("permission %s of class %s is not within scope", id, 
                                             policydbp->p_class_val_to_name[i]); 
                                } 
                                continue;             
                        } else { 
                                cur_perms->data |= 1U << (perdatum->s.value - 1); 
                        } 

                      next: 
                        cur_perms = cur_perms->next; 
                } 

                free(id); 

        } 

If the current permission is not defined for the class, then we should not simply continue the next loop, but do "goto next", since we need to move up to the next element in the cur_perms accordingly (the Nth non-zero bit and the Nth element of class_perm_node_t are all about the same class), perhaps this is a bug, am I right ?


5, I have two questions in following snippet of link_modules():

    /* copy all types, declared and required */
    for (i = 0; i < len; i++) {
        state.cur = modules[i];
        state.cur_mod_name = modules[i]->policy->name;
        ret =
            hashtab_map(modules[i]->policy->p_types.table,
                type_copy_callback, &state);
        if (ret) {
            retval = ret;
            goto cleanup;
        }
    }

    /* then copy everything else, including aliases, and fixup attributes */
    for (i = 0; i < len; i++) {
        state.cur = modules[i];
        state.cur_mod_name = modules[i]->policy->name;
        ret =
            copy_identifiers(&state, modules[i]->policy->symtab, NULL);
        if (ret) {
            retval = ret;
            goto cleanup;
        }
    }


    if (policydb_index_others(state.handle, state.base, 0)) {
        ERR(state.handle, "Error while indexing others");
        goto cleanup;
    }

    /* copy and remap the module's data over to base */
    for (i = 0; i < len; i++) {
        state.cur = modules[i];
        ret = copy_module(&state, modules[i]);
        if (ret) {
            retval = ret;
            goto cleanup;
        }
    }

1) since copy_identifers() could cover the invoke of type_copy_callback, then why we need to call it explicitly before calling copy_identifiers()?

2) copy_identifers() has been invoked before calling copy_module(), but copy_module() could invoke copy_identifers() again. Since copy_identifers() only gets called by link_modules(), could we stop copy_module() from invoking copy_identifers() once again ?

Many thanks for all your help!

Best regards,
Harry 		 	   		  

[-- Attachment #2: Type: text/html, Size: 13891 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-05-23 13:46 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-12  9:58 A few questions about module compile/link source code HarryCiao
2011-05-20  1:13 ` Joshua Brindle
2011-05-23 13:15   ` HarryCiao
2011-05-23 13:46     ` Stephen Smalley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.