diff options
author | Casey Schaufler <casey@schaufler-ca.com> | 2011-01-17 11:05:27 -0500 |
---|---|---|
committer | Casey Schaufler <casey@schaufler-ca.com> | 2011-01-17 11:05:27 -0500 |
commit | 7898e1f8e9eb1bee88c92d636e0ab93f2cbe31c6 (patch) | |
tree | d4aaa367bb42d0ff9d1e4ba227f248b5b9cd7687 /security/smack/smack_access.c | |
parent | aeda4ac3efc29e4d55989abd0a73530453aa69ba (diff) |
Subject: [PATCH] Smack: mmap controls for library containment
In the embedded world there are often situations
where libraries are updated from a variety of sources,
for a variety of reasons, and with any number of
security characteristics. These differences
might include privilege required for a given library
provided interface to function properly, as occurs
from time to time in graphics libraries. There are
also cases where it is important to limit use of
libraries based on the provider of the library and
the security aware application may make choices
based on that criteria.
These issues are addressed by providing an additional
Smack label that may optionally be assigned to an object,
the SMACK64MMAP attribute. An mmap operation is allowed
if there is no such attribute.
If there is a SMACK64MMAP attribute the mmap is permitted
only if a subject with that label has all of the access
permitted a subject with the current task label.
Security aware applications may from time to time
wish to reduce their "privilege" to avoid accidental use
of privilege. One case where this arises is the
environment in which multiple sources provide libraries
to perform the same functions. An application may know
that it should eschew services made available from a
particular vendor, or of a particular version.
In support of this a secondary list of Smack rules has
been added that is local to the task. This list is
consulted only in the case where the global list has
approved access. It can only further restrict access.
Unlike the global last, if no entry is found on the
local list access is granted. An application can add
entries to its own list by writing to /smack/load-self.
The changes appear large as they involve refactoring
the list handling to accomodate there being more
than one rule list.
Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack/smack_access.c')
-rw-r--r-- | security/smack/smack_access.c | 52 |
1 files changed, 34 insertions, 18 deletions
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 7ba8478f599e..86453db4333d 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -70,10 +70,11 @@ int log_policy = SMACK_AUDIT_DENIED; | |||
70 | * smk_access_entry - look up matching access rule | 70 | * smk_access_entry - look up matching access rule |
71 | * @subject_label: a pointer to the subject's Smack label | 71 | * @subject_label: a pointer to the subject's Smack label |
72 | * @object_label: a pointer to the object's Smack label | 72 | * @object_label: a pointer to the object's Smack label |
73 | * @rule_list: the list of rules to search | ||
73 | * | 74 | * |
74 | * This function looks up the subject/object pair in the | 75 | * This function looks up the subject/object pair in the |
75 | * access rule list and returns pointer to the matching rule if found, | 76 | * access rule list and returns the access mode. If no |
76 | * NULL otherwise. | 77 | * entry is found returns -ENOENT. |
77 | * | 78 | * |
78 | * NOTE: | 79 | * NOTE: |
79 | * Even though Smack labels are usually shared on smack_list | 80 | * Even though Smack labels are usually shared on smack_list |
@@ -85,13 +86,13 @@ int log_policy = SMACK_AUDIT_DENIED; | |||
85 | * will be on the list, so checking the pointers may be a worthwhile | 86 | * will be on the list, so checking the pointers may be a worthwhile |
86 | * optimization. | 87 | * optimization. |
87 | */ | 88 | */ |
88 | int smk_access_entry(char *subject_label, char *object_label) | 89 | int smk_access_entry(char *subject_label, char *object_label, |
90 | struct list_head *rule_list) | ||
89 | { | 91 | { |
90 | u32 may = MAY_NOT; | 92 | int may = -ENOENT; |
91 | struct smack_rule *srp; | 93 | struct smack_rule *srp; |
92 | 94 | ||
93 | rcu_read_lock(); | 95 | list_for_each_entry_rcu(srp, rule_list, list) { |
94 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
95 | if (srp->smk_subject == subject_label || | 96 | if (srp->smk_subject == subject_label || |
96 | strcmp(srp->smk_subject, subject_label) == 0) { | 97 | strcmp(srp->smk_subject, subject_label) == 0) { |
97 | if (srp->smk_object == object_label || | 98 | if (srp->smk_object == object_label || |
@@ -101,7 +102,6 @@ int smk_access_entry(char *subject_label, char *object_label) | |||
101 | } | 102 | } |
102 | } | 103 | } |
103 | } | 104 | } |
104 | rcu_read_unlock(); | ||
105 | 105 | ||
106 | return may; | 106 | return may; |
107 | } | 107 | } |
@@ -129,7 +129,7 @@ int smk_access_entry(char *subject_label, char *object_label) | |||
129 | int smk_access(char *subject_label, char *object_label, int request, | 129 | int smk_access(char *subject_label, char *object_label, int request, |
130 | struct smk_audit_info *a) | 130 | struct smk_audit_info *a) |
131 | { | 131 | { |
132 | u32 may = MAY_NOT; | 132 | int may = MAY_NOT; |
133 | int rc = 0; | 133 | int rc = 0; |
134 | 134 | ||
135 | /* | 135 | /* |
@@ -181,13 +181,14 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
181 | * Beyond here an explicit relationship is required. | 181 | * Beyond here an explicit relationship is required. |
182 | * If the requested access is contained in the available | 182 | * If the requested access is contained in the available |
183 | * access (e.g. read is included in readwrite) it's | 183 | * access (e.g. read is included in readwrite) it's |
184 | * good. | 184 | * good. A negative response from smk_access_entry() |
185 | */ | 185 | * indicates there is no entry for this pair. |
186 | may = smk_access_entry(subject_label, object_label); | ||
187 | /* | ||
188 | * This is a bit map operation. | ||
189 | */ | 186 | */ |
190 | if ((request & may) == request) | 187 | rcu_read_lock(); |
188 | may = smk_access_entry(subject_label, object_label, &smack_rule_list); | ||
189 | rcu_read_unlock(); | ||
190 | |||
191 | if (may > 0 && (request & may) == request) | ||
191 | goto out_audit; | 192 | goto out_audit; |
192 | 193 | ||
193 | rc = -EACCES; | 194 | rc = -EACCES; |
@@ -212,12 +213,27 @@ out_audit: | |||
212 | */ | 213 | */ |
213 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | 214 | int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) |
214 | { | 215 | { |
216 | struct task_smack *tsp = current_security(); | ||
217 | char *sp = smk_of_task(tsp); | ||
218 | int may; | ||
215 | int rc; | 219 | int rc; |
216 | char *sp = smk_of_current(); | ||
217 | 220 | ||
221 | /* | ||
222 | * Check the global rule list | ||
223 | */ | ||
218 | rc = smk_access(sp, obj_label, mode, NULL); | 224 | rc = smk_access(sp, obj_label, mode, NULL); |
219 | if (rc == 0) | 225 | if (rc == 0) { |
220 | goto out_audit; | 226 | /* |
227 | * If there is an entry in the task's rule list | ||
228 | * it can further restrict access. | ||
229 | */ | ||
230 | may = smk_access_entry(sp, obj_label, &tsp->smk_rules); | ||
231 | if (may < 0) | ||
232 | goto out_audit; | ||
233 | if ((mode & may) == mode) | ||
234 | goto out_audit; | ||
235 | rc = -EACCES; | ||
236 | } | ||
221 | 237 | ||
222 | /* | 238 | /* |
223 | * Return if a specific label has been designated as the | 239 | * Return if a specific label has been designated as the |
@@ -228,7 +244,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | |||
228 | goto out_audit; | 244 | goto out_audit; |
229 | 245 | ||
230 | if (capable(CAP_MAC_OVERRIDE)) | 246 | if (capable(CAP_MAC_OVERRIDE)) |
231 | return 0; | 247 | rc = 0; |
232 | 248 | ||
233 | out_audit: | 249 | out_audit: |
234 | #ifdef CONFIG_AUDIT | 250 | #ifdef CONFIG_AUDIT |