Skip to content

Commit a68916e

Browse files
bowerscd-corppcmoore
authored andcommitted
ipe: add permissive toggle
IPE, like SELinux, supports a permissive mode. This mode allows policy authors to test and evaluate IPE policy without it affecting their programs. When the mode is changed, a 1404 AUDIT_MAC_STATUS will be reported. This patch adds the following audit records: audit: MAC_STATUS enforcing=0 old_enforcing=1 auid=4294967295 ses=4294967295 enabled=1 old-enabled=1 lsm=ipe res=1 audit: MAC_STATUS enforcing=1 old_enforcing=0 auid=4294967295 ses=4294967295 enabled=1 old-enabled=1 lsm=ipe res=1 The audit record only emit when the value from the user input is different from the current enforce value. Signed-off-by: Deven Bowers <[email protected]> Signed-off-by: Fan Wu <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent f44554b commit a68916e

File tree

5 files changed

+102
-4
lines changed

5 files changed

+102
-4
lines changed

security/ipe/audit.c

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ void ipe_audit_match(const struct ipe_eval_ctx *const ctx,
9797
if (!ab)
9898
return;
9999

100-
audit_log_format(ab, "ipe_op=%s ipe_hook=%s pid=%d comm=",
101-
op, audit_hook_names[ctx->hook],
100+
audit_log_format(ab, "ipe_op=%s ipe_hook=%s enforcing=%d pid=%d comm=",
101+
op, audit_hook_names[ctx->hook], READ_ONCE(enforce),
102102
task_tgid_nr(current));
103103
audit_log_untrustedstring(ab, get_task_comm(comm, current));
104104

@@ -225,3 +225,26 @@ void ipe_audit_policy_load(const struct ipe_policy *const p)
225225

226226
audit_log_end(ab);
227227
}
228+
229+
/**
230+
* ipe_audit_enforce() - Audit a change in IPE's enforcement state.
231+
* @new_enforce: The new value enforce to be set.
232+
* @old_enforce: The old value currently in enforce.
233+
*/
234+
void ipe_audit_enforce(bool new_enforce, bool old_enforce)
235+
{
236+
struct audit_buffer *ab;
237+
238+
ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS);
239+
if (!ab)
240+
return;
241+
242+
audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
243+
"enforcing=%d old_enforcing=%d auid=%u ses=%u"
244+
" enabled=1 old-enabled=1 lsm=ipe res=1",
245+
new_enforce, old_enforce,
246+
from_kuid(&init_user_ns, audit_get_loginuid(current)),
247+
audit_get_sessionid(current));
248+
249+
audit_log_end(ab);
250+
}

security/ipe/audit.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ void ipe_audit_match(const struct ipe_eval_ctx *const ctx,
1414
void ipe_audit_policy_load(const struct ipe_policy *const p);
1515
void ipe_audit_policy_activation(const struct ipe_policy *const op,
1616
const struct ipe_policy *const np);
17+
void ipe_audit_enforce(bool new_enforce, bool old_enforce);
1718

1819
#endif /* _IPE_AUDIT_H */

security/ipe/eval.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
struct ipe_policy __rcu *ipe_active_policy;
2020
bool success_audit;
21+
bool enforce = true;
2122

2223
#define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
2324

@@ -108,6 +109,7 @@ int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
108109
enum ipe_action_type action;
109110
enum ipe_match match_type;
110111
bool match = false;
112+
int rc = 0;
111113

112114
rcu_read_lock();
113115

@@ -159,9 +161,12 @@ int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
159161
rcu_read_unlock();
160162

161163
if (action == IPE_ACTION_DENY)
162-
return -EACCES;
164+
rc = -EACCES;
163165

164-
return 0;
166+
if (!READ_ONCE(enforce))
167+
rc = 0;
168+
169+
return rc;
165170
}
166171

167172
/* Set the right module name */
@@ -172,3 +177,5 @@ int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
172177

173178
module_param(success_audit, bool, 0400);
174179
MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled");
180+
module_param(enforce, bool, 0400);
181+
MODULE_PARM_DESC(enforce, "Start IPE in enforce or permissive mode");

security/ipe/eval.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
extern struct ipe_policy __rcu *ipe_active_policy;
1818
extern bool success_audit;
19+
extern bool enforce;
1920

2021
struct ipe_superblock {
2122
bool initramfs;

security/ipe/fs.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ static struct dentry *np __ro_after_init;
1616
static struct dentry *root __ro_after_init;
1717
struct dentry *policy_root __ro_after_init;
1818
static struct dentry *audit_node __ro_after_init;
19+
static struct dentry *enforce_node __ro_after_init;
1920

2021
/**
2122
* setaudit() - Write handler for the securityfs node, "ipe/success_audit"
@@ -65,6 +66,58 @@ static ssize_t getaudit(struct file *f, char __user *data,
6566
return simple_read_from_buffer(data, len, offset, result, 1);
6667
}
6768

69+
/**
70+
* setenforce() - Write handler for the securityfs node, "ipe/enforce"
71+
* @f: Supplies a file structure representing the securityfs node.
72+
* @data: Supplies a buffer passed to the write syscall.
73+
* @len: Supplies the length of @data.
74+
* @offset: unused.
75+
*
76+
* Return:
77+
* * Length of buffer written - Success
78+
* * %-EPERM - Insufficient permission
79+
*/
80+
static ssize_t setenforce(struct file *f, const char __user *data,
81+
size_t len, loff_t *offset)
82+
{
83+
int rc = 0;
84+
bool new_value, old_value;
85+
86+
if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN))
87+
return -EPERM;
88+
89+
old_value = READ_ONCE(enforce);
90+
rc = kstrtobool_from_user(data, len, &new_value);
91+
if (rc)
92+
return rc;
93+
94+
if (new_value != old_value) {
95+
ipe_audit_enforce(new_value, old_value);
96+
WRITE_ONCE(enforce, new_value);
97+
}
98+
99+
return len;
100+
}
101+
102+
/**
103+
* getenforce() - Read handler for the securityfs node, "ipe/enforce"
104+
* @f: Supplies a file structure representing the securityfs node.
105+
* @data: Supplies a buffer passed to the read syscall.
106+
* @len: Supplies the length of @data.
107+
* @offset: unused.
108+
*
109+
* Return: Length of buffer written
110+
*/
111+
static ssize_t getenforce(struct file *f, char __user *data,
112+
size_t len, loff_t *offset)
113+
{
114+
const char *result;
115+
116+
result = ((READ_ONCE(enforce)) ? "1" : "0");
117+
118+
return simple_read_from_buffer(data, len, offset, result, 1);
119+
}
120+
68121
/**
69122
* new_policy() - Write handler for the securityfs node, "ipe/new_policy".
70123
* @f: Supplies a file structure representing the securityfs node.
@@ -123,6 +176,11 @@ static const struct file_operations audit_fops = {
123176
.read = getaudit,
124177
};
125178

179+
static const struct file_operations enforce_fops = {
180+
.write = setenforce,
181+
.read = getenforce,
182+
};
183+
126184
/**
127185
* ipe_init_securityfs() - Initialize IPE's securityfs tree at fsinit.
128186
*
@@ -149,6 +207,13 @@ static int __init ipe_init_securityfs(void)
149207
goto err;
150208
}
151209

210+
enforce_node = securityfs_create_file("enforce", 0600, root, NULL,
211+
&enforce_fops);
212+
if (IS_ERR(enforce_node)) {
213+
rc = PTR_ERR(enforce_node);
214+
goto err;
215+
}
216+
152217
policy_root = securityfs_create_dir("policies", root);
153218
if (IS_ERR(policy_root)) {
154219
rc = PTR_ERR(policy_root);
@@ -165,6 +230,7 @@ static int __init ipe_init_securityfs(void)
165230
err:
166231
securityfs_remove(np);
167232
securityfs_remove(policy_root);
233+
securityfs_remove(enforce_node);
168234
securityfs_remove(audit_node);
169235
securityfs_remove(root);
170236
return rc;

0 commit comments

Comments
 (0)