@@ -405,6 +405,63 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,
405
405
* Security Attribute Functions
406
406
*/
407
407
408
+ #define _CM_F_NONE 0x00000000
409
+ #define _CM_F_ALLOC 0x00000001
410
+
411
+ /**
412
+ * _netlbl_secattr_catmap_getnode - Get a individual node from a catmap
413
+ * @catmap: pointer to the category bitmap
414
+ * @offset: the requested offset
415
+ * @cm_flags: catmap flags, see _CM_F_*
416
+ * @gfp_flags: memory allocation flags
417
+ *
418
+ * Description:
419
+ * Iterate through the catmap looking for the node associated with @offset; if
420
+ * the _CM_F_ALLOC flag is set in @cm_flags and there is no associated node,
421
+ * one will be created and inserted into the catmap. Returns a pointer to the
422
+ * node on success, NULL on failure.
423
+ *
424
+ */
425
+ static struct netlbl_lsm_secattr_catmap * _netlbl_secattr_catmap_getnode (
426
+ struct netlbl_lsm_secattr_catmap * * catmap ,
427
+ u32 offset ,
428
+ unsigned int cm_flags ,
429
+ gfp_t gfp_flags )
430
+ {
431
+ struct netlbl_lsm_secattr_catmap * iter = * catmap ;
432
+ struct netlbl_lsm_secattr_catmap * prev = NULL ;
433
+
434
+ if (iter == NULL || offset < iter -> startbit )
435
+ goto secattr_catmap_getnode_alloc ;
436
+ while (iter && offset >= (iter -> startbit + NETLBL_CATMAP_SIZE )) {
437
+ prev = iter ;
438
+ iter = iter -> next ;
439
+ }
440
+ if (iter == NULL || offset < iter -> startbit )
441
+ goto secattr_catmap_getnode_alloc ;
442
+
443
+ return iter ;
444
+
445
+ secattr_catmap_getnode_alloc :
446
+ if (!(cm_flags & _CM_F_ALLOC ))
447
+ return NULL ;
448
+
449
+ iter = netlbl_secattr_catmap_alloc (gfp_flags );
450
+ if (iter == NULL )
451
+ return NULL ;
452
+ iter -> startbit = offset & ~(NETLBL_CATMAP_SIZE - 1 );
453
+
454
+ if (prev == NULL ) {
455
+ iter -> next = * catmap ;
456
+ * catmap = iter ;
457
+ } else {
458
+ iter -> next = prev -> next ;
459
+ prev -> next = iter ;
460
+ }
461
+
462
+ return iter ;
463
+ }
464
+
408
465
/**
409
466
* netlbl_secattr_catmap_walk - Walk a LSM secattr catmap looking for a bit
410
467
* @catmap: the category bitmap
@@ -520,6 +577,54 @@ int netlbl_secattr_catmap_walk_rng(struct netlbl_lsm_secattr_catmap *catmap,
520
577
return - ENOENT ;
521
578
}
522
579
580
+ /**
581
+ * netlbl_secattr_catmap_getlong - Export an unsigned long bitmap
582
+ * @catmap: pointer to the category bitmap
583
+ * @offset: pointer to the requested offset
584
+ * @bitmap: the exported bitmap
585
+ *
586
+ * Description:
587
+ * Export a bitmap with an offset greater than or equal to @offset and return
588
+ * it in @bitmap. The @offset must be aligned to an unsigned long and will be
589
+ * updated on return if different from what was requested; if the catmap is
590
+ * empty at the requested offset and beyond, the @offset is set to (u32)-1.
591
+ * Returns zero on sucess, negative values on failure.
592
+ *
593
+ */
594
+ int netlbl_secattr_catmap_getlong (struct netlbl_lsm_secattr_catmap * catmap ,
595
+ u32 * offset ,
596
+ unsigned long * bitmap )
597
+ {
598
+ struct netlbl_lsm_secattr_catmap * iter ;
599
+ u32 off = * offset ;
600
+ u32 idx ;
601
+
602
+ /* only allow aligned offsets */
603
+ if ((off & (BITS_PER_LONG - 1 )) != 0 )
604
+ return - EINVAL ;
605
+
606
+ if (off < catmap -> startbit ) {
607
+ off = catmap -> startbit ;
608
+ * offset = off ;
609
+ }
610
+ iter = _netlbl_secattr_catmap_getnode (& catmap , off , _CM_F_NONE , 0 );
611
+ if (iter == NULL ) {
612
+ * offset = (u32 )- 1 ;
613
+ return 0 ;
614
+ }
615
+
616
+ if (off < iter -> startbit ) {
617
+ off = iter -> startbit ;
618
+ * offset = off ;
619
+ } else
620
+ off -= iter -> startbit ;
621
+
622
+ idx = off / NETLBL_CATMAP_MAPSIZE ;
623
+ * bitmap = iter -> bitmap [idx ] >> (off % NETLBL_CATMAP_SIZE );
624
+
625
+ return 0 ;
626
+ }
627
+
523
628
/**
524
629
* netlbl_secattr_catmap_setbit - Set a bit in a LSM secattr catmap
525
630
* @catmap: pointer to the category bitmap
@@ -535,32 +640,16 @@ int netlbl_secattr_catmap_setbit(struct netlbl_lsm_secattr_catmap **catmap,
535
640
u32 bit ,
536
641
gfp_t flags )
537
642
{
538
- struct netlbl_lsm_secattr_catmap * iter = * catmap ;
539
- u32 node_bit ;
540
- u32 node_idx ;
643
+ struct netlbl_lsm_secattr_catmap * iter ;
644
+ u32 idx ;
541
645
542
- while (iter -> next != NULL &&
543
- bit >= (iter -> startbit + NETLBL_CATMAP_SIZE ))
544
- iter = iter -> next ;
545
- if (bit < iter -> startbit ) {
546
- iter = netlbl_secattr_catmap_alloc (flags );
547
- if (iter == NULL )
548
- return - ENOMEM ;
549
- iter -> next = * catmap ;
550
- iter -> startbit = bit & ~(NETLBL_CATMAP_SIZE - 1 );
551
- * catmap = iter ;
552
- } else if (bit >= (iter -> startbit + NETLBL_CATMAP_SIZE )) {
553
- iter -> next = netlbl_secattr_catmap_alloc (flags );
554
- if (iter -> next == NULL )
555
- return - ENOMEM ;
556
- iter = iter -> next ;
557
- iter -> startbit = bit & ~(NETLBL_CATMAP_SIZE - 1 );
558
- }
646
+ iter = _netlbl_secattr_catmap_getnode (catmap , bit , _CM_F_ALLOC , flags );
647
+ if (iter == NULL )
648
+ return - ENOMEM ;
559
649
560
- /* gcc always rounds to zero when doing integer division */
561
- node_idx = (bit - iter -> startbit ) / NETLBL_CATMAP_MAPSIZE ;
562
- node_bit = bit - iter -> startbit - (NETLBL_CATMAP_MAPSIZE * node_idx );
563
- iter -> bitmap [node_idx ] |= NETLBL_CATMAP_BIT << node_bit ;
650
+ bit -= iter -> startbit ;
651
+ idx = bit / NETLBL_CATMAP_MAPSIZE ;
652
+ iter -> bitmap [idx ] |= NETLBL_CATMAP_BIT << (bit % NETLBL_CATMAP_MAPSIZE );
564
653
565
654
return 0 ;
566
655
}
@@ -582,34 +671,61 @@ int netlbl_secattr_catmap_setrng(struct netlbl_lsm_secattr_catmap **catmap,
582
671
u32 end ,
583
672
gfp_t flags )
584
673
{
585
- int ret_val = 0 ;
586
- struct netlbl_lsm_secattr_catmap * iter = * catmap ;
587
- u32 iter_max_spot ;
588
- u32 spot ;
589
- u32 orig_spot = iter -> startbit ;
590
-
591
- /* XXX - This could probably be made a bit faster by combining writes
592
- * to the catmap instead of setting a single bit each time, but for
593
- * right now skipping to the start of the range in the catmap should
594
- * be a nice improvement over calling the individual setbit function
595
- * repeatedly from a loop. */
596
-
597
- while (iter -> next != NULL &&
598
- start >= (iter -> startbit + NETLBL_CATMAP_SIZE ))
599
- iter = iter -> next ;
600
- iter_max_spot = iter -> startbit + NETLBL_CATMAP_SIZE ;
601
-
602
- for (spot = start ; spot <= end && ret_val == 0 ; spot ++ ) {
603
- if (spot >= iter_max_spot && iter -> next != NULL ) {
604
- iter = iter -> next ;
605
- iter_max_spot = iter -> startbit + NETLBL_CATMAP_SIZE ;
606
- }
607
- ret_val = netlbl_secattr_catmap_setbit (& iter , spot , flags );
608
- if (iter -> startbit < orig_spot )
609
- * catmap = iter ;
674
+ int rc = 0 ;
675
+ u32 spot = start ;
676
+
677
+ while (rc == 0 && spot <= end ) {
678
+ if (((spot & (BITS_PER_LONG - 1 )) != 0 ) &&
679
+ ((end - spot ) > BITS_PER_LONG )) {
680
+ rc = netlbl_secattr_catmap_setlong (catmap ,
681
+ spot ,
682
+ (unsigned long )-1 ,
683
+ flags );
684
+ spot += BITS_PER_LONG ;
685
+ } else
686
+ rc = netlbl_secattr_catmap_setbit (catmap ,
687
+ spot ++ ,
688
+ flags );
610
689
}
611
690
612
- return ret_val ;
691
+ return rc ;
692
+ }
693
+
694
+ /**
695
+ * netlbl_secattr_catmap_setlong - Import an unsigned long bitmap
696
+ * @catmap: pointer to the category bitmap
697
+ * @offset: offset to the start of the imported bitmap
698
+ * @bitmap: the bitmap to import
699
+ * @flags: memory allocation flags
700
+ *
701
+ * Description:
702
+ * Import the bitmap specified in @bitmap into @catmap, using the offset
703
+ * in @offset. The offset must be aligned to an unsigned long. Returns zero
704
+ * on success, negative values on failure.
705
+ *
706
+ */
707
+ int netlbl_secattr_catmap_setlong (struct netlbl_lsm_secattr_catmap * * catmap ,
708
+ u32 offset ,
709
+ unsigned long bitmap ,
710
+ gfp_t flags )
711
+ {
712
+ struct netlbl_lsm_secattr_catmap * iter ;
713
+ u32 idx ;
714
+
715
+ /* only allow aligned offsets */
716
+ if ((offset & (BITS_PER_LONG - 1 )) != 0 )
717
+ return - EINVAL ;
718
+
719
+ iter = _netlbl_secattr_catmap_getnode (catmap ,
720
+ offset , _CM_F_ALLOC , flags );
721
+ if (iter == NULL )
722
+ return - ENOMEM ;
723
+
724
+ offset -= iter -> startbit ;
725
+ idx = offset / NETLBL_CATMAP_MAPSIZE ;
726
+ iter -> bitmap [idx ] |= bitmap << (offset % NETLBL_CATMAP_MAPSIZE );
727
+
728
+ return 0 ;
613
729
}
614
730
615
731
/*
0 commit comments