OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [fs/] [posix_acl.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * linux/fs/posix_acl.c
3
 *
4
 *  Copyright (C) 2002 by Andreas Gruenbacher <a.gruenbacher@computer.org>
5
 *
6
 *  Fixes from William Schumacher incorporated on 15 March 2001.
7
 *     (Reported by Charles Bertsch, <CBertsch@microtest.com>).
8
 */
9
 
10
/*
11
 *  This file contains generic functions for manipulating
12
 *  POSIX 1003.1e draft standard 17 ACLs.
13
 */
14
 
15
#include <linux/kernel.h>
16
#include <linux/slab.h>
17
#include <asm/atomic.h>
18
#include <linux/fs.h>
19
#include <linux/sched.h>
20
#include <linux/posix_acl.h>
21
#include <linux/module.h>
22
 
23
#include <linux/errno.h>
24
 
25
EXPORT_SYMBOL(posix_acl_alloc);
26
EXPORT_SYMBOL(posix_acl_clone);
27
EXPORT_SYMBOL(posix_acl_valid);
28
EXPORT_SYMBOL(posix_acl_equiv_mode);
29
EXPORT_SYMBOL(posix_acl_from_mode);
30
EXPORT_SYMBOL(posix_acl_create_masq);
31
EXPORT_SYMBOL(posix_acl_chmod_masq);
32
EXPORT_SYMBOL(posix_acl_permission);
33
 
34
/*
35
 * Allocate a new ACL with the specified number of entries.
36
 */
37
struct posix_acl *
38
posix_acl_alloc(int count, gfp_t flags)
39
{
40
        const size_t size = sizeof(struct posix_acl) +
41
                            count * sizeof(struct posix_acl_entry);
42
        struct posix_acl *acl = kmalloc(size, flags);
43
        if (acl) {
44
                atomic_set(&acl->a_refcount, 1);
45
                acl->a_count = count;
46
        }
47
        return acl;
48
}
49
 
50
/*
51
 * Clone an ACL.
52
 */
53
struct posix_acl *
54
posix_acl_clone(const struct posix_acl *acl, gfp_t flags)
55
{
56
        struct posix_acl *clone = NULL;
57
 
58
        if (acl) {
59
                int size = sizeof(struct posix_acl) + acl->a_count *
60
                           sizeof(struct posix_acl_entry);
61
                clone = kmemdup(acl, size, flags);
62
                if (clone)
63
                        atomic_set(&clone->a_refcount, 1);
64
        }
65
        return clone;
66
}
67
 
68
/*
69
 * Check if an acl is valid. Returns 0 if it is, or -E... otherwise.
70
 */
71
int
72
posix_acl_valid(const struct posix_acl *acl)
73
{
74
        const struct posix_acl_entry *pa, *pe;
75
        int state = ACL_USER_OBJ;
76
        unsigned int id = 0;  /* keep gcc happy */
77
        int needs_mask = 0;
78
 
79
        FOREACH_ACL_ENTRY(pa, acl, pe) {
80
                if (pa->e_perm & ~(ACL_READ|ACL_WRITE|ACL_EXECUTE))
81
                        return -EINVAL;
82
                switch (pa->e_tag) {
83
                        case ACL_USER_OBJ:
84
                                if (state == ACL_USER_OBJ) {
85
                                        id = 0;
86
                                        state = ACL_USER;
87
                                        break;
88
                                }
89
                                return -EINVAL;
90
 
91
                        case ACL_USER:
92
                                if (state != ACL_USER)
93
                                        return -EINVAL;
94
                                if (pa->e_id == ACL_UNDEFINED_ID ||
95
                                    pa->e_id < id)
96
                                        return -EINVAL;
97
                                id = pa->e_id + 1;
98
                                needs_mask = 1;
99
                                break;
100
 
101
                        case ACL_GROUP_OBJ:
102
                                if (state == ACL_USER) {
103
                                        id = 0;
104
                                        state = ACL_GROUP;
105
                                        break;
106
                                }
107
                                return -EINVAL;
108
 
109
                        case ACL_GROUP:
110
                                if (state != ACL_GROUP)
111
                                        return -EINVAL;
112
                                if (pa->e_id == ACL_UNDEFINED_ID ||
113
                                    pa->e_id < id)
114
                                        return -EINVAL;
115
                                id = pa->e_id + 1;
116
                                needs_mask = 1;
117
                                break;
118
 
119
                        case ACL_MASK:
120
                                if (state != ACL_GROUP)
121
                                        return -EINVAL;
122
                                state = ACL_OTHER;
123
                                break;
124
 
125
                        case ACL_OTHER:
126
                                if (state == ACL_OTHER ||
127
                                    (state == ACL_GROUP && !needs_mask)) {
128
                                        state = 0;
129
                                        break;
130
                                }
131
                                return -EINVAL;
132
 
133
                        default:
134
                                return -EINVAL;
135
                }
136
        }
137
        if (state == 0)
138
                return 0;
139
        return -EINVAL;
140
}
141
 
142
/*
143
 * Returns 0 if the acl can be exactly represented in the traditional
144
 * file mode permission bits, or else 1. Returns -E... on error.
145
 */
146
int
147
posix_acl_equiv_mode(const struct posix_acl *acl, mode_t *mode_p)
148
{
149
        const struct posix_acl_entry *pa, *pe;
150
        mode_t mode = 0;
151
        int not_equiv = 0;
152
 
153
        FOREACH_ACL_ENTRY(pa, acl, pe) {
154
                switch (pa->e_tag) {
155
                        case ACL_USER_OBJ:
156
                                mode |= (pa->e_perm & S_IRWXO) << 6;
157
                                break;
158
                        case ACL_GROUP_OBJ:
159
                                mode |= (pa->e_perm & S_IRWXO) << 3;
160
                                break;
161
                        case ACL_OTHER:
162
                                mode |= pa->e_perm & S_IRWXO;
163
                                break;
164
                        case ACL_MASK:
165
                                mode = (mode & ~S_IRWXG) |
166
                                       ((pa->e_perm & S_IRWXO) << 3);
167
                                not_equiv = 1;
168
                                break;
169
                        case ACL_USER:
170
                        case ACL_GROUP:
171
                                not_equiv = 1;
172
                                break;
173
                        default:
174
                                return -EINVAL;
175
                }
176
        }
177
        if (mode_p)
178
                *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
179
        return not_equiv;
180
}
181
 
182
/*
183
 * Create an ACL representing the file mode permission bits of an inode.
184
 */
185
struct posix_acl *
186
posix_acl_from_mode(mode_t mode, gfp_t flags)
187
{
188
        struct posix_acl *acl = posix_acl_alloc(3, flags);
189
        if (!acl)
190
                return ERR_PTR(-ENOMEM);
191
 
192
        acl->a_entries[0].e_tag  = ACL_USER_OBJ;
193
        acl->a_entries[0].e_id   = ACL_UNDEFINED_ID;
194
        acl->a_entries[0].e_perm = (mode & S_IRWXU) >> 6;
195
 
196
        acl->a_entries[1].e_tag  = ACL_GROUP_OBJ;
197
        acl->a_entries[1].e_id   = ACL_UNDEFINED_ID;
198
        acl->a_entries[1].e_perm = (mode & S_IRWXG) >> 3;
199
 
200
        acl->a_entries[2].e_tag  = ACL_OTHER;
201
        acl->a_entries[2].e_id   = ACL_UNDEFINED_ID;
202
        acl->a_entries[2].e_perm = (mode & S_IRWXO);
203
        return acl;
204
}
205
 
206
/*
207
 * Return 0 if current is granted want access to the inode
208
 * by the acl. Returns -E... otherwise.
209
 */
210
int
211
posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
212
{
213
        const struct posix_acl_entry *pa, *pe, *mask_obj;
214
        int found = 0;
215
 
216
        FOREACH_ACL_ENTRY(pa, acl, pe) {
217
                switch(pa->e_tag) {
218
                        case ACL_USER_OBJ:
219
                                /* (May have been checked already) */
220
                                if (inode->i_uid == current->fsuid)
221
                                        goto check_perm;
222
                                break;
223
                        case ACL_USER:
224
                                if (pa->e_id == current->fsuid)
225
                                        goto mask;
226
                                break;
227
                        case ACL_GROUP_OBJ:
228
                                if (in_group_p(inode->i_gid)) {
229
                                        found = 1;
230
                                        if ((pa->e_perm & want) == want)
231
                                                goto mask;
232
                                }
233
                                break;
234
                        case ACL_GROUP:
235
                                if (in_group_p(pa->e_id)) {
236
                                        found = 1;
237
                                        if ((pa->e_perm & want) == want)
238
                                                goto mask;
239
                                }
240
                                break;
241
                        case ACL_MASK:
242
                                break;
243
                        case ACL_OTHER:
244
                                if (found)
245
                                        return -EACCES;
246
                                else
247
                                        goto check_perm;
248
                        default:
249
                                return -EIO;
250
                }
251
        }
252
        return -EIO;
253
 
254
mask:
255
        for (mask_obj = pa+1; mask_obj != pe; mask_obj++) {
256
                if (mask_obj->e_tag == ACL_MASK) {
257
                        if ((pa->e_perm & mask_obj->e_perm & want) == want)
258
                                return 0;
259
                        return -EACCES;
260
                }
261
        }
262
 
263
check_perm:
264
        if ((pa->e_perm & want) == want)
265
                return 0;
266
        return -EACCES;
267
}
268
 
269
/*
270
 * Modify acl when creating a new inode. The caller must ensure the acl is
271
 * only referenced once.
272
 *
273
 * mode_p initially must contain the mode parameter to the open() / creat()
274
 * system calls. All permissions that are not granted by the acl are removed.
275
 * The permissions in the acl are changed to reflect the mode_p parameter.
276
 */
277
int
278
posix_acl_create_masq(struct posix_acl *acl, mode_t *mode_p)
279
{
280
        struct posix_acl_entry *pa, *pe;
281
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
282
        mode_t mode = *mode_p;
283
        int not_equiv = 0;
284
 
285
        /* assert(atomic_read(acl->a_refcount) == 1); */
286
 
287
        FOREACH_ACL_ENTRY(pa, acl, pe) {
288
                switch(pa->e_tag) {
289
                        case ACL_USER_OBJ:
290
                                pa->e_perm &= (mode >> 6) | ~S_IRWXO;
291
                                mode &= (pa->e_perm << 6) | ~S_IRWXU;
292
                                break;
293
 
294
                        case ACL_USER:
295
                        case ACL_GROUP:
296
                                not_equiv = 1;
297
                                break;
298
 
299
                        case ACL_GROUP_OBJ:
300
                                group_obj = pa;
301
                                break;
302
 
303
                        case ACL_OTHER:
304
                                pa->e_perm &= mode | ~S_IRWXO;
305
                                mode &= pa->e_perm | ~S_IRWXO;
306
                                break;
307
 
308
                        case ACL_MASK:
309
                                mask_obj = pa;
310
                                not_equiv = 1;
311
                                break;
312
 
313
                        default:
314
                                return -EIO;
315
                }
316
        }
317
 
318
        if (mask_obj) {
319
                mask_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
320
                mode &= (mask_obj->e_perm << 3) | ~S_IRWXG;
321
        } else {
322
                if (!group_obj)
323
                        return -EIO;
324
                group_obj->e_perm &= (mode >> 3) | ~S_IRWXO;
325
                mode &= (group_obj->e_perm << 3) | ~S_IRWXG;
326
        }
327
 
328
        *mode_p = (*mode_p & ~S_IRWXUGO) | mode;
329
        return not_equiv;
330
}
331
 
332
/*
333
 * Modify the ACL for the chmod syscall.
334
 */
335
int
336
posix_acl_chmod_masq(struct posix_acl *acl, mode_t mode)
337
{
338
        struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL;
339
        struct posix_acl_entry *pa, *pe;
340
 
341
        /* assert(atomic_read(acl->a_refcount) == 1); */
342
 
343
        FOREACH_ACL_ENTRY(pa, acl, pe) {
344
                switch(pa->e_tag) {
345
                        case ACL_USER_OBJ:
346
                                pa->e_perm = (mode & S_IRWXU) >> 6;
347
                                break;
348
 
349
                        case ACL_USER:
350
                        case ACL_GROUP:
351
                                break;
352
 
353
                        case ACL_GROUP_OBJ:
354
                                group_obj = pa;
355
                                break;
356
 
357
                        case ACL_MASK:
358
                                mask_obj = pa;
359
                                break;
360
 
361
                        case ACL_OTHER:
362
                                pa->e_perm = (mode & S_IRWXO);
363
                                break;
364
 
365
                        default:
366
                                return -EIO;
367
                }
368
        }
369
 
370
        if (mask_obj) {
371
                mask_obj->e_perm = (mode & S_IRWXG) >> 3;
372
        } else {
373
                if (!group_obj)
374
                        return -EIO;
375
                group_obj->e_perm = (mode & S_IRWXG) >> 3;
376
        }
377
 
378
        return 0;
379
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.