~ubuntu-branches/ubuntu/lucid/linux-rt/lucid

« back to all changes in this revision

Viewing changes to security/smack/smack_access.c

  • Committer: Bazaar Package Importer
  • Author(s): Luke Yelavich
  • Date: 2009-08-05 23:00:52 UTC
  • Revision ID: james.westby@ubuntu.com-20090805230052-7xedvqcyk9dnnxb2
Tags: 2.6.31-1.1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#include "smack.h"
17
17
 
18
18
struct smack_known smack_known_huh = {
19
 
        .smk_next       = NULL,
20
19
        .smk_known      = "?",
21
20
        .smk_secid      = 2,
22
21
        .smk_cipso      = NULL,
23
22
};
24
23
 
25
24
struct smack_known smack_known_hat = {
26
 
        .smk_next       = &smack_known_huh,
27
25
        .smk_known      = "^",
28
26
        .smk_secid      = 3,
29
27
        .smk_cipso      = NULL,
30
28
};
31
29
 
32
30
struct smack_known smack_known_star = {
33
 
        .smk_next       = &smack_known_hat,
34
31
        .smk_known      = "*",
35
32
        .smk_secid      = 4,
36
33
        .smk_cipso      = NULL,
37
34
};
38
35
 
39
36
struct smack_known smack_known_floor = {
40
 
        .smk_next       = &smack_known_star,
41
37
        .smk_known      = "_",
42
38
        .smk_secid      = 5,
43
39
        .smk_cipso      = NULL,
44
40
};
45
41
 
46
42
struct smack_known smack_known_invalid = {
47
 
        .smk_next       = &smack_known_floor,
48
43
        .smk_known      = "",
49
44
        .smk_secid      = 6,
50
45
        .smk_cipso      = NULL,
51
46
};
52
47
 
53
48
struct smack_known smack_known_web = {
54
 
        .smk_next       = &smack_known_invalid,
55
49
        .smk_known      = "@",
56
50
        .smk_secid      = 7,
57
51
        .smk_cipso      = NULL,
58
52
};
59
53
 
60
 
struct smack_known *smack_known = &smack_known_web;
 
54
LIST_HEAD(smack_known_list);
61
55
 
62
56
/*
63
57
 * The initial value needs to be bigger than any of the
65
59
 */
66
60
static u32 smack_next_secid = 10;
67
61
 
 
62
/*
 
63
 * what events do we log
 
64
 * can be overwritten at run-time by /smack/logging
 
65
 */
 
66
int log_policy = SMACK_AUDIT_DENIED;
 
67
 
68
68
/**
69
69
 * smk_access - determine if a subject has a specific access to an object
70
70
 * @subject_label: a pointer to the subject's Smack label
71
71
 * @object_label: a pointer to the object's Smack label
72
72
 * @request: the access requested, in "MAY" format
 
73
 * @a : a pointer to the audit data
73
74
 *
74
75
 * This function looks up the subject/object pair in the
75
76
 * access rule list and returns 0 if the access is permitted,
84
85
 * will be on the list, so checking the pointers may be a worthwhile
85
86
 * optimization.
86
87
 */
87
 
int smk_access(char *subject_label, char *object_label, int request)
 
88
int smk_access(char *subject_label, char *object_label, int request,
 
89
               struct smk_audit_info *a)
88
90
{
89
91
        u32 may = MAY_NOT;
90
 
        struct smk_list_entry *sp;
91
92
        struct smack_rule *srp;
 
93
        int rc = 0;
92
94
 
93
95
        /*
94
96
         * Hardcoded comparisons.
96
98
         * A star subject can't access any object.
97
99
         */
98
100
        if (subject_label == smack_known_star.smk_known ||
99
 
            strcmp(subject_label, smack_known_star.smk_known) == 0)
100
 
                return -EACCES;
 
101
            strcmp(subject_label, smack_known_star.smk_known) == 0) {
 
102
                rc = -EACCES;
 
103
                goto out_audit;
 
104
        }
101
105
        /*
102
106
         * An internet object can be accessed by any subject.
103
107
         * Tasks cannot be assigned the internet label.
107
111
            subject_label == smack_known_web.smk_known ||
108
112
            strcmp(object_label, smack_known_web.smk_known) == 0 ||
109
113
            strcmp(subject_label, smack_known_web.smk_known) == 0)
110
 
                return 0;
 
114
                goto out_audit;
111
115
        /*
112
116
         * A star object can be accessed by any subject.
113
117
         */
114
118
        if (object_label == smack_known_star.smk_known ||
115
119
            strcmp(object_label, smack_known_star.smk_known) == 0)
116
 
                return 0;
 
120
                goto out_audit;
117
121
        /*
118
122
         * An object can be accessed in any way by a subject
119
123
         * with the same label.
120
124
         */
121
125
        if (subject_label == object_label ||
122
126
            strcmp(subject_label, object_label) == 0)
123
 
                return 0;
 
127
                goto out_audit;
124
128
        /*
125
129
         * A hat subject can read any object.
126
130
         * A floor object can be read by any subject.
128
132
        if ((request & MAY_ANYREAD) == request) {
129
133
                if (object_label == smack_known_floor.smk_known ||
130
134
                    strcmp(object_label, smack_known_floor.smk_known) == 0)
131
 
                        return 0;
 
135
                        goto out_audit;
132
136
                if (subject_label == smack_known_hat.smk_known ||
133
137
                    strcmp(subject_label, smack_known_hat.smk_known) == 0)
134
 
                        return 0;
 
138
                        goto out_audit;
135
139
        }
136
140
        /*
137
141
         * Beyond here an explicit relationship is required.
139
143
         * access (e.g. read is included in readwrite) it's
140
144
         * good.
141
145
         */
142
 
        for (sp = smack_list; sp != NULL; sp = sp->smk_next) {
143
 
                srp = &sp->smk_rule;
144
 
 
 
146
        rcu_read_lock();
 
147
        list_for_each_entry_rcu(srp, &smack_rule_list, list) {
145
148
                if (srp->smk_subject == subject_label ||
146
149
                    strcmp(srp->smk_subject, subject_label) == 0) {
147
150
                        if (srp->smk_object == object_label ||
151
154
                        }
152
155
                }
153
156
        }
 
157
        rcu_read_unlock();
154
158
        /*
155
159
         * This is a bit map operation.
156
160
         */
157
161
        if ((request & may) == request)
158
 
                return 0;
 
162
                goto out_audit;
159
163
 
160
 
        return -EACCES;
 
164
        rc = -EACCES;
 
165
out_audit:
 
166
#ifdef CONFIG_AUDIT
 
167
        if (a)
 
168
                smack_log(subject_label, object_label, request, rc, a);
 
169
#endif
 
170
        return rc;
161
171
}
162
172
 
163
173
/**
164
174
 * smk_curacc - determine if current has a specific access to an object
165
 
 * @object_label: a pointer to the object's Smack label
166
 
 * @request: the access requested, in "MAY" format
 
175
 * @obj_label: a pointer to the object's Smack label
 
176
 * @mode: the access requested, in "MAY" format
 
177
 * @a : common audit data
167
178
 *
168
179
 * This function checks the current subject label/object label pair
169
180
 * in the access rule list and returns 0 if the access is permitted,
170
181
 * non zero otherwise. It allows that current may have the capability
171
182
 * to override the rules.
172
183
 */
173
 
int smk_curacc(char *obj_label, u32 mode)
 
184
int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
174
185
{
175
186
        int rc;
 
187
        char *sp = current_security();
176
188
 
177
 
        rc = smk_access(current_security(), obj_label, mode);
 
189
        rc = smk_access(sp, obj_label, mode, NULL);
178
190
        if (rc == 0)
179
 
                return 0;
 
191
                goto out_audit;
180
192
 
181
193
        /*
182
194
         * Return if a specific label has been designated as the
184
196
         * have that label.
185
197
         */
186
198
        if (smack_onlycap != NULL && smack_onlycap != current->cred->security)
187
 
                return rc;
 
199
                goto out_audit;
188
200
 
189
201
        if (capable(CAP_MAC_OVERRIDE))
190
202
                return 0;
191
203
 
 
204
out_audit:
 
205
#ifdef CONFIG_AUDIT
 
206
        if (a)
 
207
                smack_log(sp, obj_label, mode, rc, a);
 
208
#endif
192
209
        return rc;
193
210
}
194
211
 
 
212
#ifdef CONFIG_AUDIT
 
213
/**
 
214
 * smack_str_from_perm : helper to transalate an int to a
 
215
 * readable string
 
216
 * @string : the string to fill
 
217
 * @access : the int
 
218
 *
 
219
 */
 
220
static inline void smack_str_from_perm(char *string, int access)
 
221
{
 
222
        int i = 0;
 
223
        if (access & MAY_READ)
 
224
                string[i++] = 'r';
 
225
        if (access & MAY_WRITE)
 
226
                string[i++] = 'w';
 
227
        if (access & MAY_EXEC)
 
228
                string[i++] = 'x';
 
229
        if (access & MAY_APPEND)
 
230
                string[i++] = 'a';
 
231
        string[i] = '\0';
 
232
}
 
233
/**
 
234
 * smack_log_callback - SMACK specific information
 
235
 * will be called by generic audit code
 
236
 * @ab : the audit_buffer
 
237
 * @a  : audit_data
 
238
 *
 
239
 */
 
240
static void smack_log_callback(struct audit_buffer *ab, void *a)
 
241
{
 
242
        struct common_audit_data *ad = a;
 
243
        struct smack_audit_data *sad = &ad->lsm_priv.smack_audit_data;
 
244
        audit_log_format(ab, "lsm=SMACK fn=%s action=%s", ad->function,
 
245
                         sad->result ? "denied" : "granted");
 
246
        audit_log_format(ab, " subject=");
 
247
        audit_log_untrustedstring(ab, sad->subject);
 
248
        audit_log_format(ab, " object=");
 
249
        audit_log_untrustedstring(ab, sad->object);
 
250
        audit_log_format(ab, " requested=%s", sad->request);
 
251
}
 
252
 
 
253
/**
 
254
 *  smack_log - Audit the granting or denial of permissions.
 
255
 *  @subject_label : smack label of the requester
 
256
 *  @object_label  : smack label of the object being accessed
 
257
 *  @request: requested permissions
 
258
 *  @result: result from smk_access
 
259
 *  @a:  auxiliary audit data
 
260
 *
 
261
 * Audit the granting or denial of permissions in accordance
 
262
 * with the policy.
 
263
 */
 
264
void smack_log(char *subject_label, char *object_label, int request,
 
265
               int result, struct smk_audit_info *ad)
 
266
{
 
267
        char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
 
268
        struct smack_audit_data *sad;
 
269
        struct common_audit_data *a = &ad->a;
 
270
 
 
271
        /* check if we have to log the current event */
 
272
        if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
 
273
                return;
 
274
        if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
 
275
                return;
 
276
 
 
277
        if (a->function == NULL)
 
278
                a->function = "unknown";
 
279
 
 
280
        /* end preparing the audit data */
 
281
        sad = &a->lsm_priv.smack_audit_data;
 
282
        smack_str_from_perm(request_buffer, request);
 
283
        sad->subject = subject_label;
 
284
        sad->object  = object_label;
 
285
        sad->request = request_buffer;
 
286
        sad->result  = result;
 
287
        a->lsm_pre_audit = smack_log_callback;
 
288
 
 
289
        common_lsm_audit(a);
 
290
}
 
291
#else /* #ifdef CONFIG_AUDIT */
 
292
void smack_log(char *subject_label, char *object_label, int request,
 
293
               int result, struct smk_audit_info *ad)
 
294
{
 
295
}
 
296
#endif
 
297
 
195
298
static DEFINE_MUTEX(smack_known_lock);
196
299
 
197
300
/**
216
319
                if (found)
217
320
                        smack[i] = '\0';
218
321
                else if (i >= len || string[i] > '~' || string[i] <= ' ' ||
219
 
                         string[i] == '/') {
 
322
                         string[i] == '/' || string[i] == '"' ||
 
323
                         string[i] == '\\' || string[i] == '\'') {
220
324
                        smack[i] = '\0';
221
325
                        found = 1;
222
326
                } else
228
332
 
229
333
        mutex_lock(&smack_known_lock);
230
334
 
231
 
        for (skp = smack_known; skp != NULL; skp = skp->smk_next)
232
 
                if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
 
335
        found = 0;
 
336
        list_for_each_entry_rcu(skp, &smack_known_list, list) {
 
337
                if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
 
338
                        found = 1;
233
339
                        break;
 
340
                }
 
341
        }
234
342
 
235
 
        if (skp == NULL) {
 
343
        if (found == 0) {
236
344
                skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL);
237
345
                if (skp != NULL) {
238
 
                        skp->smk_next = smack_known;
239
346
                        strncpy(skp->smk_known, smack, SMK_MAXLEN);
240
347
                        skp->smk_secid = smack_next_secid++;
241
348
                        skp->smk_cipso = NULL;
244
351
                         * Make sure that the entry is actually
245
352
                         * filled before putting it on the list.
246
353
                         */
247
 
                        smp_mb();
248
 
                        smack_known = skp;
 
354
                        list_add_rcu(&skp->list, &smack_known_list);
249
355
                }
250
356
        }
251
357
 
266
372
{
267
373
        struct smack_known *skp;
268
374
 
 
375
        /* labels cannot begin with a '-' */
 
376
        if (string[0] == '-')
 
377
                return NULL;
269
378
        skp = smk_import_entry(string, len);
270
379
        if (skp == NULL)
271
380
                return NULL;
283
392
{
284
393
        struct smack_known *skp;
285
394
 
286
 
        for (skp = smack_known; skp != NULL; skp = skp->smk_next)
287
 
                if (skp->smk_secid == secid)
 
395
        rcu_read_lock();
 
396
        list_for_each_entry_rcu(skp, &smack_known_list, list) {
 
397
                if (skp->smk_secid == secid) {
 
398
                        rcu_read_unlock();
288
399
                        return skp->smk_known;
 
400
                }
 
401
        }
289
402
 
290
403
        /*
291
404
         * If we got this far someone asked for the translation
292
405
         * of a secid that is not on the list.
293
406
         */
 
407
        rcu_read_unlock();
294
408
        return smack_known_invalid.smk_known;
295
409
}
296
410
 
305
419
{
306
420
        struct smack_known *skp;
307
421
 
308
 
        for (skp = smack_known; skp != NULL; skp = skp->smk_next)
309
 
                if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0)
 
422
        rcu_read_lock();
 
423
        list_for_each_entry_rcu(skp, &smack_known_list, list) {
 
424
                if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) {
 
425
                        rcu_read_unlock();
310
426
                        return skp->smk_secid;
 
427
                }
 
428
        }
 
429
        rcu_read_unlock();
311
430
        return 0;
312
431
}
313
432
 
332
451
        struct smack_known *kp;
333
452
        char *final = NULL;
334
453
 
335
 
        for (kp = smack_known; final == NULL && kp != NULL; kp = kp->smk_next) {
 
454
        rcu_read_lock();
 
455
        list_for_each_entry(kp, &smack_known_list, list) {
336
456
                if (kp->smk_cipso == NULL)
337
457
                        continue;
338
458
 
344
464
 
345
465
                spin_unlock_bh(&kp->smk_cipsolock);
346
466
        }
 
467
        rcu_read_unlock();
347
468
        if (final == NULL)
348
469
                final = smack_known_huh.smk_known;
349
470
        strncpy(result, final, SMK_MAXLEN);
360
481
int smack_to_cipso(const char *smack, struct smack_cipso *cp)
361
482
{
362
483
        struct smack_known *kp;
 
484
        int found = 0;
363
485
 
364
 
        for (kp = smack_known; kp != NULL; kp = kp->smk_next)
 
486
        rcu_read_lock();
 
487
        list_for_each_entry_rcu(kp, &smack_known_list, list) {
365
488
                if (kp->smk_known == smack ||
366
 
                    strcmp(kp->smk_known, smack) == 0)
 
489
                    strcmp(kp->smk_known, smack) == 0) {
 
490
                        found = 1;
367
491
                        break;
 
492
                }
 
493
        }
 
494
        rcu_read_unlock();
368
495
 
369
 
        if (kp == NULL || kp->smk_cipso == NULL)
 
496
        if (found == 0 || kp->smk_cipso == NULL)
370
497
                return -ENOENT;
371
498
 
372
499
        memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso));