4747#include <asm/bug.h>
4848#include <asm/unaligned.h>
4949
50- struct cipso_v4_domhsh_entry {
51- char * domain ;
52- u32 valid ;
53- struct list_head list ;
54- struct rcu_head rcu ;
55- };
56-
5750/* List of available DOI definitions */
58- /* XXX - Updates should be minimal so having a single lock for the
59- * cipso_v4_doi_list and the cipso_v4_doi_list->dom_list should be
60- * okay. */
6151/* XXX - This currently assumes a minimal number of different DOIs in use,
6252 * if in practice there are a lot of different DOIs this list should
6353 * probably be turned into a hash table or something similar so we
@@ -193,25 +183,6 @@ static void cipso_v4_bitmap_setbit(unsigned char *bitmap,
193183 bitmap [byte_spot ] &= ~bitmask ;
194184}
195185
196- /**
197- * cipso_v4_doi_domhsh_free - Frees a domain list entry
198- * @entry: the entry's RCU field
199- *
200- * Description:
201- * This function is designed to be used as a callback to the call_rcu()
202- * function so that the memory allocated to a domain list entry can be released
203- * safely.
204- *
205- */
206- static void cipso_v4_doi_domhsh_free (struct rcu_head * entry )
207- {
208- struct cipso_v4_domhsh_entry * ptr ;
209-
210- ptr = container_of (entry , struct cipso_v4_domhsh_entry , rcu );
211- kfree (ptr -> domain );
212- kfree (ptr );
213- }
214-
215186/**
216187 * cipso_v4_cache_entry_free - Frees a cache entry
217188 * @entry: the entry to free
@@ -457,7 +428,7 @@ static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi)
457428 struct cipso_v4_doi * iter ;
458429
459430 list_for_each_entry_rcu (iter , & cipso_v4_doi_list , list )
460- if (iter -> doi == doi && iter -> valid )
431+ if (iter -> doi == doi && atomic_read ( & iter -> refcount ) )
461432 return iter ;
462433 return NULL ;
463434}
@@ -501,9 +472,8 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
501472 }
502473 }
503474
504- doi_def -> valid = 1 ;
475+ atomic_set ( & doi_def -> refcount , 1 ) ;
505476 INIT_RCU_HEAD (& doi_def -> rcu );
506- INIT_LIST_HEAD (& doi_def -> dom_list );
507477
508478 spin_lock (& cipso_v4_doi_list_lock );
509479 if (cipso_v4_doi_search (doi_def -> doi ) != NULL )
@@ -518,60 +488,130 @@ int cipso_v4_doi_add(struct cipso_v4_doi *doi_def)
518488 return - EEXIST ;
519489}
520490
491+ /**
492+ * cipso_v4_doi_free - Frees a DOI definition
493+ * @entry: the entry's RCU field
494+ *
495+ * Description:
496+ * This function frees all of the memory associated with a DOI definition.
497+ *
498+ */
499+ void cipso_v4_doi_free (struct cipso_v4_doi * doi_def )
500+ {
501+ if (doi_def == NULL )
502+ return ;
503+
504+ switch (doi_def -> type ) {
505+ case CIPSO_V4_MAP_STD :
506+ kfree (doi_def -> map .std -> lvl .cipso );
507+ kfree (doi_def -> map .std -> lvl .local );
508+ kfree (doi_def -> map .std -> cat .cipso );
509+ kfree (doi_def -> map .std -> cat .local );
510+ break ;
511+ }
512+ kfree (doi_def );
513+ }
514+
515+ /**
516+ * cipso_v4_doi_free_rcu - Frees a DOI definition via the RCU pointer
517+ * @entry: the entry's RCU field
518+ *
519+ * Description:
520+ * This function is designed to be used as a callback to the call_rcu()
521+ * function so that the memory allocated to the DOI definition can be released
522+ * safely.
523+ *
524+ */
525+ static void cipso_v4_doi_free_rcu (struct rcu_head * entry )
526+ {
527+ struct cipso_v4_doi * doi_def ;
528+
529+ doi_def = container_of (entry , struct cipso_v4_doi , rcu );
530+ cipso_v4_doi_free (doi_def );
531+ }
532+
521533/**
522534 * cipso_v4_doi_remove - Remove an existing DOI from the CIPSO protocol engine
523535 * @doi: the DOI value
524536 * @audit_secid: the LSM secid to use in the audit message
525- * @callback: the DOI cleanup/free callback
526537 *
527538 * Description:
528- * Removes a DOI definition from the CIPSO engine, @callback is called to
529- * free any memory. The NetLabel routines will be called to release their own
530- * LSM domain mappings as well as our own domain list. Returns zero on
531- * success and negative values on failure.
539+ * Removes a DOI definition from the CIPSO engine. The NetLabel routines will
540+ * be called to release their own LSM domain mappings as well as our own
541+ * domain list. Returns zero on success and negative values on failure.
532542 *
533543 */
534- int cipso_v4_doi_remove (u32 doi ,
535- struct netlbl_audit * audit_info ,
536- void (* callback ) (struct rcu_head * head ))
544+ int cipso_v4_doi_remove (u32 doi , struct netlbl_audit * audit_info )
537545{
538546 struct cipso_v4_doi * doi_def ;
539- struct cipso_v4_domhsh_entry * dom_iter ;
540547
541548 spin_lock (& cipso_v4_doi_list_lock );
542549 doi_def = cipso_v4_doi_search (doi );
543- if (doi_def != NULL ) {
544- doi_def -> valid = 0 ;
545- list_del_rcu (& doi_def -> list );
550+ if (doi_def == NULL ) {
546551 spin_unlock (& cipso_v4_doi_list_lock );
547- rcu_read_lock ();
548- list_for_each_entry_rcu (dom_iter , & doi_def -> dom_list , list )
549- if (dom_iter -> valid )
550- netlbl_cfg_map_del (dom_iter -> domain ,
551- audit_info );
552- rcu_read_unlock ();
553- cipso_v4_cache_invalidate ();
554- call_rcu (& doi_def -> rcu , callback );
555- return 0 ;
552+ return - ENOENT ;
553+ }
554+ if (!atomic_dec_and_test (& doi_def -> refcount )) {
555+ spin_unlock (& cipso_v4_doi_list_lock );
556+ return - EBUSY ;
556557 }
558+ list_del_rcu (& doi_def -> list );
557559 spin_unlock (& cipso_v4_doi_list_lock );
558560
559- return - ENOENT ;
561+ cipso_v4_cache_invalidate ();
562+ call_rcu (& doi_def -> rcu , cipso_v4_doi_free_rcu );
563+
564+ return 0 ;
560565}
561566
562567/**
563- * cipso_v4_doi_getdef - Returns a pointer to a valid DOI definition
568+ * cipso_v4_doi_getdef - Returns a reference to a valid DOI definition
564569 * @doi: the DOI value
565570 *
566571 * Description:
567572 * Searches for a valid DOI definition and if one is found it is returned to
568573 * the caller. Otherwise NULL is returned. The caller must ensure that
569- * rcu_read_lock() is held while accessing the returned definition.
574+ * rcu_read_lock() is held while accessing the returned definition and the DOI
575+ * definition reference count is decremented when the caller is done.
570576 *
571577 */
572578struct cipso_v4_doi * cipso_v4_doi_getdef (u32 doi )
573579{
574- return cipso_v4_doi_search (doi );
580+ struct cipso_v4_doi * doi_def ;
581+
582+ rcu_read_lock ();
583+ doi_def = cipso_v4_doi_search (doi );
584+ if (doi_def == NULL )
585+ goto doi_getdef_return ;
586+ if (!atomic_inc_not_zero (& doi_def -> refcount ))
587+ doi_def = NULL ;
588+
589+ doi_getdef_return :
590+ rcu_read_unlock ();
591+ return doi_def ;
592+ }
593+
594+ /**
595+ * cipso_v4_doi_putdef - Releases a reference for the given DOI definition
596+ * @doi_def: the DOI definition
597+ *
598+ * Description:
599+ * Releases a DOI definition reference obtained from cipso_v4_doi_getdef().
600+ *
601+ */
602+ void cipso_v4_doi_putdef (struct cipso_v4_doi * doi_def )
603+ {
604+ if (doi_def == NULL )
605+ return ;
606+
607+ if (!atomic_dec_and_test (& doi_def -> refcount ))
608+ return ;
609+ spin_lock (& cipso_v4_doi_list_lock );
610+ list_del_rcu (& doi_def -> list );
611+ spin_unlock (& cipso_v4_doi_list_lock );
612+
613+ cipso_v4_cache_invalidate ();
614+ call_rcu (& doi_def -> rcu , cipso_v4_doi_free_rcu );
575615}
576616
577617/**
@@ -597,7 +637,7 @@ int cipso_v4_doi_walk(u32 *skip_cnt,
597637
598638 rcu_read_lock ();
599639 list_for_each_entry_rcu (iter_doi , & cipso_v4_doi_list , list )
600- if (iter_doi -> valid ) {
640+ if (atomic_read ( & iter_doi -> refcount ) > 0 ) {
601641 if (doi_cnt ++ < * skip_cnt )
602642 continue ;
603643 ret_val = callback (iter_doi , cb_arg );
@@ -613,85 +653,6 @@ int cipso_v4_doi_walk(u32 *skip_cnt,
613653 return ret_val ;
614654}
615655
616- /**
617- * cipso_v4_doi_domhsh_add - Adds a domain entry to a DOI definition
618- * @doi_def: the DOI definition
619- * @domain: the domain to add
620- *
621- * Description:
622- * Adds the @domain to the DOI specified by @doi_def, this function
623- * should only be called by external functions (i.e. NetLabel). This function
624- * does allocate memory. Returns zero on success, negative values on failure.
625- *
626- */
627- int cipso_v4_doi_domhsh_add (struct cipso_v4_doi * doi_def , const char * domain )
628- {
629- struct cipso_v4_domhsh_entry * iter ;
630- struct cipso_v4_domhsh_entry * new_dom ;
631-
632- new_dom = kzalloc (sizeof (* new_dom ), GFP_KERNEL );
633- if (new_dom == NULL )
634- return - ENOMEM ;
635- if (domain ) {
636- new_dom -> domain = kstrdup (domain , GFP_KERNEL );
637- if (new_dom -> domain == NULL ) {
638- kfree (new_dom );
639- return - ENOMEM ;
640- }
641- }
642- new_dom -> valid = 1 ;
643- INIT_RCU_HEAD (& new_dom -> rcu );
644-
645- spin_lock (& cipso_v4_doi_list_lock );
646- list_for_each_entry (iter , & doi_def -> dom_list , list )
647- if (iter -> valid &&
648- ((domain != NULL && iter -> domain != NULL &&
649- strcmp (iter -> domain , domain ) == 0 ) ||
650- (domain == NULL && iter -> domain == NULL ))) {
651- spin_unlock (& cipso_v4_doi_list_lock );
652- kfree (new_dom -> domain );
653- kfree (new_dom );
654- return - EEXIST ;
655- }
656- list_add_tail_rcu (& new_dom -> list , & doi_def -> dom_list );
657- spin_unlock (& cipso_v4_doi_list_lock );
658-
659- return 0 ;
660- }
661-
662- /**
663- * cipso_v4_doi_domhsh_remove - Removes a domain entry from a DOI definition
664- * @doi_def: the DOI definition
665- * @domain: the domain to remove
666- *
667- * Description:
668- * Removes the @domain from the DOI specified by @doi_def, this function
669- * should only be called by external functions (i.e. NetLabel). Returns zero
670- * on success and negative values on error.
671- *
672- */
673- int cipso_v4_doi_domhsh_remove (struct cipso_v4_doi * doi_def ,
674- const char * domain )
675- {
676- struct cipso_v4_domhsh_entry * iter ;
677-
678- spin_lock (& cipso_v4_doi_list_lock );
679- list_for_each_entry (iter , & doi_def -> dom_list , list )
680- if (iter -> valid &&
681- ((domain != NULL && iter -> domain != NULL &&
682- strcmp (iter -> domain , domain ) == 0 ) ||
683- (domain == NULL && iter -> domain == NULL ))) {
684- iter -> valid = 0 ;
685- list_del_rcu (& iter -> list );
686- spin_unlock (& cipso_v4_doi_list_lock );
687- call_rcu (& iter -> rcu , cipso_v4_doi_domhsh_free );
688- return 0 ;
689- }
690- spin_unlock (& cipso_v4_doi_list_lock );
691-
692- return - ENOENT ;
693- }
694-
695656/*
696657 * Label Mapping Functions
697658 */
0 commit comments