~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to security/selinux/ss/status.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * mmap based event notifications for SELinux
 
3
 *
 
4
 * Author: KaiGai Kohei <kaigai@ak.jp.nec.com>
 
5
 *
 
6
 * Copyright (C) 2010 NEC corporation
 
7
 *
 
8
 * This program is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU General Public License version 2,
 
10
 * as published by the Free Software Foundation.
 
11
 */
 
12
#include <linux/kernel.h>
 
13
#include <linux/gfp.h>
 
14
#include <linux/mm.h>
 
15
#include <linux/mutex.h>
 
16
#include "avc.h"
 
17
#include "services.h"
 
18
 
 
19
/*
 
20
 * The selinux_status_page shall be exposed to userspace applications
 
21
 * using mmap interface on /selinux/status.
 
22
 * It enables to notify applications a few events that will cause reset
 
23
 * of userspace access vector without context switching.
 
24
 *
 
25
 * The selinux_kernel_status structure on the head of status page is
 
26
 * protected from concurrent accesses using seqlock logic, so userspace
 
27
 * application should reference the status page according to the seqlock
 
28
 * logic.
 
29
 *
 
30
 * Typically, application checks status->sequence at the head of access
 
31
 * control routine. If it is odd-number, kernel is updating the status,
 
32
 * so please wait for a moment. If it is changed from the last sequence
 
33
 * number, it means something happen, so application will reset userspace
 
34
 * avc, if needed.
 
35
 * In most cases, application shall confirm the kernel status is not
 
36
 * changed without any system call invocations.
 
37
 */
 
38
static struct page *selinux_status_page;
 
39
static DEFINE_MUTEX(selinux_status_lock);
 
40
 
 
41
/*
 
42
 * selinux_kernel_status_page
 
43
 *
 
44
 * It returns a reference to selinux_status_page. If the status page is
 
45
 * not allocated yet, it also tries to allocate it at the first time.
 
46
 */
 
47
struct page *selinux_kernel_status_page(void)
 
48
{
 
49
        struct selinux_kernel_status   *status;
 
50
        struct page                    *result = NULL;
 
51
 
 
52
        mutex_lock(&selinux_status_lock);
 
53
        if (!selinux_status_page) {
 
54
                selinux_status_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
 
55
 
 
56
                if (selinux_status_page) {
 
57
                        status = page_address(selinux_status_page);
 
58
 
 
59
                        status->version = SELINUX_KERNEL_STATUS_VERSION;
 
60
                        status->sequence = 0;
 
61
                        status->enforcing = selinux_enforcing;
 
62
                        /*
 
63
                         * NOTE: the next policyload event shall set
 
64
                         * a positive value on the status->policyload,
 
65
                         * although it may not be 1, but never zero.
 
66
                         * So, application can know it was updated.
 
67
                         */
 
68
                        status->policyload = 0;
 
69
                        status->deny_unknown = !security_get_allow_unknown();
 
70
                }
 
71
        }
 
72
        result = selinux_status_page;
 
73
        mutex_unlock(&selinux_status_lock);
 
74
 
 
75
        return result;
 
76
}
 
77
 
 
78
/*
 
79
 * selinux_status_update_setenforce
 
80
 *
 
81
 * It updates status of the current enforcing/permissive mode.
 
82
 */
 
83
void selinux_status_update_setenforce(int enforcing)
 
84
{
 
85
        struct selinux_kernel_status   *status;
 
86
 
 
87
        mutex_lock(&selinux_status_lock);
 
88
        if (selinux_status_page) {
 
89
                status = page_address(selinux_status_page);
 
90
 
 
91
                status->sequence++;
 
92
                smp_wmb();
 
93
 
 
94
                status->enforcing = enforcing;
 
95
 
 
96
                smp_wmb();
 
97
                status->sequence++;
 
98
        }
 
99
        mutex_unlock(&selinux_status_lock);
 
100
}
 
101
 
 
102
/*
 
103
 * selinux_status_update_policyload
 
104
 *
 
105
 * It updates status of the times of policy reloaded, and current
 
106
 * setting of deny_unknown.
 
107
 */
 
108
void selinux_status_update_policyload(int seqno)
 
109
{
 
110
        struct selinux_kernel_status   *status;
 
111
 
 
112
        mutex_lock(&selinux_status_lock);
 
113
        if (selinux_status_page) {
 
114
                status = page_address(selinux_status_page);
 
115
 
 
116
                status->sequence++;
 
117
                smp_wmb();
 
118
 
 
119
                status->policyload = seqno;
 
120
                status->deny_unknown = !security_get_allow_unknown();
 
121
 
 
122
                smp_wmb();
 
123
                status->sequence++;
 
124
        }
 
125
        mutex_unlock(&selinux_status_lock);
 
126
}