aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/ebitmap.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2010-10-13 17:50:25 -0400
committerJames Morris <jmorris@namei.org>2010-10-20 19:12:58 -0400
commitcee74f47a6baba0ac457e87687fdcf0abd599f0a (patch)
tree3d9fdb073050664e62d9cdb6c28112090cd138da /security/selinux/ss/ebitmap.c
parent00d85c83ac52e2c1a66397f1abc589f80c543425 (diff)
SELinux: allow userspace to read policy back out of the kernel
There is interest in being able to see what the actual policy is that was loaded into the kernel. The patch creates a new selinuxfs file /selinux/policy which can be read by userspace. The actual policy that is loaded into the kernel will be written back out to userspace. Signed-off-by: Eric Paris <eparis@redhat.com> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/ss/ebitmap.c')
-rw-r--r--security/selinux/ss/ebitmap.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index 04b6145d767f..d42951fcbe87 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -22,6 +22,8 @@
22#include "ebitmap.h" 22#include "ebitmap.h"
23#include "policydb.h" 23#include "policydb.h"
24 24
25#define BITS_PER_U64 (sizeof(u64) * 8)
26
25int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2) 27int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
26{ 28{
27 struct ebitmap_node *n1, *n2; 29 struct ebitmap_node *n1, *n2;
@@ -363,10 +365,10 @@ int ebitmap_read(struct ebitmap *e, void *fp)
363 e->highbit = le32_to_cpu(buf[1]); 365 e->highbit = le32_to_cpu(buf[1]);
364 count = le32_to_cpu(buf[2]); 366 count = le32_to_cpu(buf[2]);
365 367
366 if (mapunit != sizeof(u64) * 8) { 368 if (mapunit != BITS_PER_U64) {
367 printk(KERN_ERR "SELinux: ebitmap: map size %u does not " 369 printk(KERN_ERR "SELinux: ebitmap: map size %u does not "
368 "match my size %Zd (high bit was %d)\n", 370 "match my size %Zd (high bit was %d)\n",
369 mapunit, sizeof(u64) * 8, e->highbit); 371 mapunit, BITS_PER_U64, e->highbit);
370 goto bad; 372 goto bad;
371 } 373 }
372 374
@@ -446,3 +448,78 @@ bad:
446 ebitmap_destroy(e); 448 ebitmap_destroy(e);
447 goto out; 449 goto out;
448} 450}
451
452int ebitmap_write(struct ebitmap *e, void *fp)
453{
454 struct ebitmap_node *n;
455 u32 count;
456 __le32 buf[3];
457 u64 map;
458 int bit, last_bit, last_startbit, rc;
459
460 buf[0] = cpu_to_le32(BITS_PER_U64);
461
462 count = 0;
463 last_bit = 0;
464 last_startbit = -1;
465 ebitmap_for_each_positive_bit(e, n, bit) {
466 if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
467 count++;
468 last_startbit = rounddown(bit, BITS_PER_U64);
469 }
470 last_bit = roundup(bit + 1, BITS_PER_U64);
471 }
472 buf[1] = cpu_to_le32(last_bit);
473 buf[2] = cpu_to_le32(count);
474
475 rc = put_entry(buf, sizeof(u32), 3, fp);
476 if (rc)
477 return rc;
478
479 map = 0;
480 last_startbit = INT_MIN;
481 ebitmap_for_each_positive_bit(e, n, bit) {
482 if (rounddown(bit, (int)BITS_PER_U64) > last_startbit) {
483 __le64 buf64[1];
484
485 /* this is the very first bit */
486 if (!map) {
487 last_startbit = rounddown(bit, BITS_PER_U64);
488 map = (u64)1 << (bit - last_startbit);
489 continue;
490 }
491
492 /* write the last node */
493 buf[0] = cpu_to_le32(last_startbit);
494 rc = put_entry(buf, sizeof(u32), 1, fp);
495 if (rc)
496 return rc;
497
498 buf64[0] = cpu_to_le64(map);
499 rc = put_entry(buf64, sizeof(u64), 1, fp);
500 if (rc)
501 return rc;
502
503 /* set up for the next node */
504 map = 0;
505 last_startbit = rounddown(bit, BITS_PER_U64);
506 }
507 map |= (u64)1 << (bit - last_startbit);
508 }
509 /* write the last node */
510 if (map) {
511 __le64 buf64[1];
512
513 /* write the last node */
514 buf[0] = cpu_to_le32(last_startbit);
515 rc = put_entry(buf, sizeof(u32), 1, fp);
516 if (rc)
517 return rc;
518
519 buf64[0] = cpu_to_le64(map);
520 rc = put_entry(buf64, sizeof(u64), 1, fp);
521 if (rc)
522 return rc;
523 }
524 return 0;
525}