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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [fs/] [xattr.c] - Blame information for rev 65

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
  File: fs/xattr.c
3
 
4
  Extended attribute handling.
5
 
6
  Copyright (C) 2001 by Andreas Gruenbacher <a.gruenbacher@computer.org>
7
  Copyright (C) 2001 SGI - Silicon Graphics, Inc <linux-xfs@oss.sgi.com>
8
  Copyright (c) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
9
 */
10
#include <linux/fs.h>
11
#include <linux/slab.h>
12
#include <linux/file.h>
13
#include <linux/xattr.h>
14
#include <linux/namei.h>
15
#include <linux/security.h>
16
#include <linux/syscalls.h>
17
#include <linux/module.h>
18
#include <linux/fsnotify.h>
19
#include <linux/audit.h>
20
#include <asm/uaccess.h>
21
 
22
 
23
/*
24
 * Check permissions for extended attribute access.  This is a bit complicated
25
 * because different namespaces have very different rules.
26
 */
27
static int
28
xattr_permission(struct inode *inode, const char *name, int mask)
29
{
30
        /*
31
         * We can never set or remove an extended attribute on a read-only
32
         * filesystem  or on an immutable / append-only inode.
33
         */
34
        if (mask & MAY_WRITE) {
35
                if (IS_RDONLY(inode))
36
                        return -EROFS;
37
                if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
38
                        return -EPERM;
39
        }
40
 
41
        /*
42
         * No restriction for security.* and system.* from the VFS.  Decision
43
         * on these is left to the underlying filesystem / security module.
44
         */
45
        if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
46
            !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
47
                return 0;
48
 
49
        /*
50
         * The trusted.* namespace can only be accessed by a privileged user.
51
         */
52
        if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
53
                return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
54
 
55
        /* In user.* namespace, only regular files and directories can have
56
         * extended attributes. For sticky directories, only the owner and
57
         * privileged user can write attributes.
58
         */
59
        if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
60
                if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode))
61
                        return -EPERM;
62
                if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) &&
63
                    (mask & MAY_WRITE) && !is_owner_or_cap(inode))
64
                        return -EPERM;
65
        }
66
 
67
        return permission(inode, mask, NULL);
68
}
69
 
70
int
71
vfs_setxattr(struct dentry *dentry, char *name, void *value,
72
                size_t size, int flags)
73
{
74
        struct inode *inode = dentry->d_inode;
75
        int error;
76
 
77
        error = xattr_permission(inode, name, MAY_WRITE);
78
        if (error)
79
                return error;
80
 
81
        mutex_lock(&inode->i_mutex);
82
        error = security_inode_setxattr(dentry, name, value, size, flags);
83
        if (error)
84
                goto out;
85
        error = -EOPNOTSUPP;
86
        if (inode->i_op->setxattr) {
87
                error = inode->i_op->setxattr(dentry, name, value, size, flags);
88
                if (!error) {
89
                        fsnotify_xattr(dentry);
90
                        security_inode_post_setxattr(dentry, name, value,
91
                                                     size, flags);
92
                }
93
        } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
94
                                XATTR_SECURITY_PREFIX_LEN)) {
95
                const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
96
                error = security_inode_setsecurity(inode, suffix, value,
97
                                                   size, flags);
98
                if (!error)
99
                        fsnotify_xattr(dentry);
100
        }
101
out:
102
        mutex_unlock(&inode->i_mutex);
103
        return error;
104
}
105
EXPORT_SYMBOL_GPL(vfs_setxattr);
106
 
107
ssize_t
108
vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
109
{
110
        struct inode *inode = dentry->d_inode;
111
        int error;
112
 
113
        error = xattr_permission(inode, name, MAY_READ);
114
        if (error)
115
                return error;
116
 
117
        error = security_inode_getxattr(dentry, name);
118
        if (error)
119
                return error;
120
 
121
        if (inode->i_op->getxattr)
122
                error = inode->i_op->getxattr(dentry, name, value, size);
123
        else
124
                error = -EOPNOTSUPP;
125
 
126
        if (!strncmp(name, XATTR_SECURITY_PREFIX,
127
                                XATTR_SECURITY_PREFIX_LEN)) {
128
                const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
129
                int ret = security_inode_getsecurity(inode, suffix, value,
130
                                                     size, error);
131
                /*
132
                 * Only overwrite the return value if a security module
133
                 * is actually active.
134
                 */
135
                if (ret != -EOPNOTSUPP)
136
                        error = ret;
137
        }
138
 
139
        return error;
140
}
141
EXPORT_SYMBOL_GPL(vfs_getxattr);
142
 
143
ssize_t
144
vfs_listxattr(struct dentry *d, char *list, size_t size)
145
{
146
        ssize_t error;
147
 
148
        error = security_inode_listxattr(d);
149
        if (error)
150
                return error;
151
        error = -EOPNOTSUPP;
152
        if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
153
                error = d->d_inode->i_op->listxattr(d, list, size);
154
        } else {
155
                error = security_inode_listsecurity(d->d_inode, list, size);
156
                if (size && error > size)
157
                        error = -ERANGE;
158
        }
159
        return error;
160
}
161
EXPORT_SYMBOL_GPL(vfs_listxattr);
162
 
163
int
164
vfs_removexattr(struct dentry *dentry, char *name)
165
{
166
        struct inode *inode = dentry->d_inode;
167
        int error;
168
 
169
        if (!inode->i_op->removexattr)
170
                return -EOPNOTSUPP;
171
 
172
        error = xattr_permission(inode, name, MAY_WRITE);
173
        if (error)
174
                return error;
175
 
176
        error = security_inode_removexattr(dentry, name);
177
        if (error)
178
                return error;
179
 
180
        mutex_lock(&inode->i_mutex);
181
        error = inode->i_op->removexattr(dentry, name);
182
        mutex_unlock(&inode->i_mutex);
183
 
184
        if (!error)
185
                fsnotify_xattr(dentry);
186
        return error;
187
}
188
EXPORT_SYMBOL_GPL(vfs_removexattr);
189
 
190
 
191
/*
192
 * Extended attribute SET operations
193
 */
194
static long
195
setxattr(struct dentry *d, char __user *name, void __user *value,
196
         size_t size, int flags)
197
{
198
        int error;
199
        void *kvalue = NULL;
200
        char kname[XATTR_NAME_MAX + 1];
201
 
202
        if (flags & ~(XATTR_CREATE|XATTR_REPLACE))
203
                return -EINVAL;
204
 
205
        error = strncpy_from_user(kname, name, sizeof(kname));
206
        if (error == 0 || error == sizeof(kname))
207
                error = -ERANGE;
208
        if (error < 0)
209
                return error;
210
 
211
        if (size) {
212
                if (size > XATTR_SIZE_MAX)
213
                        return -E2BIG;
214
                kvalue = kmalloc(size, GFP_KERNEL);
215
                if (!kvalue)
216
                        return -ENOMEM;
217
                if (copy_from_user(kvalue, value, size)) {
218
                        kfree(kvalue);
219
                        return -EFAULT;
220
                }
221
        }
222
 
223
        error = vfs_setxattr(d, kname, kvalue, size, flags);
224
        kfree(kvalue);
225
        return error;
226
}
227
 
228
asmlinkage long
229
sys_setxattr(char __user *path, char __user *name, void __user *value,
230
             size_t size, int flags)
231
{
232
        struct nameidata nd;
233
        int error;
234
 
235
        error = user_path_walk(path, &nd);
236
        if (error)
237
                return error;
238
        error = setxattr(nd.dentry, name, value, size, flags);
239
        path_release(&nd);
240
        return error;
241
}
242
 
243
asmlinkage long
244
sys_lsetxattr(char __user *path, char __user *name, void __user *value,
245
              size_t size, int flags)
246
{
247
        struct nameidata nd;
248
        int error;
249
 
250
        error = user_path_walk_link(path, &nd);
251
        if (error)
252
                return error;
253
        error = setxattr(nd.dentry, name, value, size, flags);
254
        path_release(&nd);
255
        return error;
256
}
257
 
258
asmlinkage long
259
sys_fsetxattr(int fd, char __user *name, void __user *value,
260
              size_t size, int flags)
261
{
262
        struct file *f;
263
        struct dentry *dentry;
264
        int error = -EBADF;
265
 
266
        f = fget(fd);
267
        if (!f)
268
                return error;
269
        dentry = f->f_path.dentry;
270
        audit_inode(NULL, dentry);
271
        error = setxattr(dentry, name, value, size, flags);
272
        fput(f);
273
        return error;
274
}
275
 
276
/*
277
 * Extended attribute GET operations
278
 */
279
static ssize_t
280
getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
281
{
282
        ssize_t error;
283
        void *kvalue = NULL;
284
        char kname[XATTR_NAME_MAX + 1];
285
 
286
        error = strncpy_from_user(kname, name, sizeof(kname));
287
        if (error == 0 || error == sizeof(kname))
288
                error = -ERANGE;
289
        if (error < 0)
290
                return error;
291
 
292
        if (size) {
293
                if (size > XATTR_SIZE_MAX)
294
                        size = XATTR_SIZE_MAX;
295
                kvalue = kzalloc(size, GFP_KERNEL);
296
                if (!kvalue)
297
                        return -ENOMEM;
298
        }
299
 
300
        error = vfs_getxattr(d, kname, kvalue, size);
301
        if (error > 0) {
302
                if (size && copy_to_user(value, kvalue, error))
303
                        error = -EFAULT;
304
        } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
305
                /* The file system tried to returned a value bigger
306
                   than XATTR_SIZE_MAX bytes. Not possible. */
307
                error = -E2BIG;
308
        }
309
        kfree(kvalue);
310
        return error;
311
}
312
 
313
asmlinkage ssize_t
314
sys_getxattr(char __user *path, char __user *name, void __user *value,
315
             size_t size)
316
{
317
        struct nameidata nd;
318
        ssize_t error;
319
 
320
        error = user_path_walk(path, &nd);
321
        if (error)
322
                return error;
323
        error = getxattr(nd.dentry, name, value, size);
324
        path_release(&nd);
325
        return error;
326
}
327
 
328
asmlinkage ssize_t
329
sys_lgetxattr(char __user *path, char __user *name, void __user *value,
330
              size_t size)
331
{
332
        struct nameidata nd;
333
        ssize_t error;
334
 
335
        error = user_path_walk_link(path, &nd);
336
        if (error)
337
                return error;
338
        error = getxattr(nd.dentry, name, value, size);
339
        path_release(&nd);
340
        return error;
341
}
342
 
343
asmlinkage ssize_t
344
sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size)
345
{
346
        struct file *f;
347
        ssize_t error = -EBADF;
348
 
349
        f = fget(fd);
350
        if (!f)
351
                return error;
352
        audit_inode(NULL, f->f_path.dentry);
353
        error = getxattr(f->f_path.dentry, name, value, size);
354
        fput(f);
355
        return error;
356
}
357
 
358
/*
359
 * Extended attribute LIST operations
360
 */
361
static ssize_t
362
listxattr(struct dentry *d, char __user *list, size_t size)
363
{
364
        ssize_t error;
365
        char *klist = NULL;
366
 
367
        if (size) {
368
                if (size > XATTR_LIST_MAX)
369
                        size = XATTR_LIST_MAX;
370
                klist = kmalloc(size, GFP_KERNEL);
371
                if (!klist)
372
                        return -ENOMEM;
373
        }
374
 
375
        error = vfs_listxattr(d, klist, size);
376
        if (error > 0) {
377
                if (size && copy_to_user(list, klist, error))
378
                        error = -EFAULT;
379
        } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
380
                /* The file system tried to returned a list bigger
381
                   than XATTR_LIST_MAX bytes. Not possible. */
382
                error = -E2BIG;
383
        }
384
        kfree(klist);
385
        return error;
386
}
387
 
388
asmlinkage ssize_t
389
sys_listxattr(char __user *path, char __user *list, size_t size)
390
{
391
        struct nameidata nd;
392
        ssize_t error;
393
 
394
        error = user_path_walk(path, &nd);
395
        if (error)
396
                return error;
397
        error = listxattr(nd.dentry, list, size);
398
        path_release(&nd);
399
        return error;
400
}
401
 
402
asmlinkage ssize_t
403
sys_llistxattr(char __user *path, char __user *list, size_t size)
404
{
405
        struct nameidata nd;
406
        ssize_t error;
407
 
408
        error = user_path_walk_link(path, &nd);
409
        if (error)
410
                return error;
411
        error = listxattr(nd.dentry, list, size);
412
        path_release(&nd);
413
        return error;
414
}
415
 
416
asmlinkage ssize_t
417
sys_flistxattr(int fd, char __user *list, size_t size)
418
{
419
        struct file *f;
420
        ssize_t error = -EBADF;
421
 
422
        f = fget(fd);
423
        if (!f)
424
                return error;
425
        audit_inode(NULL, f->f_path.dentry);
426
        error = listxattr(f->f_path.dentry, list, size);
427
        fput(f);
428
        return error;
429
}
430
 
431
/*
432
 * Extended attribute REMOVE operations
433
 */
434
static long
435
removexattr(struct dentry *d, char __user *name)
436
{
437
        int error;
438
        char kname[XATTR_NAME_MAX + 1];
439
 
440
        error = strncpy_from_user(kname, name, sizeof(kname));
441
        if (error == 0 || error == sizeof(kname))
442
                error = -ERANGE;
443
        if (error < 0)
444
                return error;
445
 
446
        return vfs_removexattr(d, kname);
447
}
448
 
449
asmlinkage long
450
sys_removexattr(char __user *path, char __user *name)
451
{
452
        struct nameidata nd;
453
        int error;
454
 
455
        error = user_path_walk(path, &nd);
456
        if (error)
457
                return error;
458
        error = removexattr(nd.dentry, name);
459
        path_release(&nd);
460
        return error;
461
}
462
 
463
asmlinkage long
464
sys_lremovexattr(char __user *path, char __user *name)
465
{
466
        struct nameidata nd;
467
        int error;
468
 
469
        error = user_path_walk_link(path, &nd);
470
        if (error)
471
                return error;
472
        error = removexattr(nd.dentry, name);
473
        path_release(&nd);
474
        return error;
475
}
476
 
477
asmlinkage long
478
sys_fremovexattr(int fd, char __user *name)
479
{
480
        struct file *f;
481
        struct dentry *dentry;
482
        int error = -EBADF;
483
 
484
        f = fget(fd);
485
        if (!f)
486
                return error;
487
        dentry = f->f_path.dentry;
488
        audit_inode(NULL, dentry);
489
        error = removexattr(dentry, name);
490
        fput(f);
491
        return error;
492
}
493
 
494
 
495
static const char *
496
strcmp_prefix(const char *a, const char *a_prefix)
497
{
498
        while (*a_prefix && *a == *a_prefix) {
499
                a++;
500
                a_prefix++;
501
        }
502
        return *a_prefix ? NULL : a;
503
}
504
 
505
/*
506
 * In order to implement different sets of xattr operations for each xattr
507
 * prefix with the generic xattr API, a filesystem should create a
508
 * null-terminated array of struct xattr_handler (one for each prefix) and
509
 * hang a pointer to it off of the s_xattr field of the superblock.
510
 *
511
 * The generic_fooxattr() functions will use this list to dispatch xattr
512
 * operations to the correct xattr_handler.
513
 */
514
#define for_each_xattr_handler(handlers, handler)               \
515
                for ((handler) = *(handlers)++;                 \
516
                        (handler) != NULL;                      \
517
                        (handler) = *(handlers)++)
518
 
519
/*
520
 * Find the xattr_handler with the matching prefix.
521
 */
522
static struct xattr_handler *
523
xattr_resolve_name(struct xattr_handler **handlers, const char **name)
524
{
525
        struct xattr_handler *handler;
526
 
527
        if (!*name)
528
                return NULL;
529
 
530
        for_each_xattr_handler(handlers, handler) {
531
                const char *n = strcmp_prefix(*name, handler->prefix);
532
                if (n) {
533
                        *name = n;
534
                        break;
535
                }
536
        }
537
        return handler;
538
}
539
 
540
/*
541
 * Find the handler for the prefix and dispatch its get() operation.
542
 */
543
ssize_t
544
generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size)
545
{
546
        struct xattr_handler *handler;
547
        struct inode *inode = dentry->d_inode;
548
 
549
        handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
550
        if (!handler)
551
                return -EOPNOTSUPP;
552
        return handler->get(inode, name, buffer, size);
553
}
554
 
555
/*
556
 * Combine the results of the list() operation from every xattr_handler in the
557
 * list.
558
 */
559
ssize_t
560
generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size)
561
{
562
        struct inode *inode = dentry->d_inode;
563
        struct xattr_handler *handler, **handlers = inode->i_sb->s_xattr;
564
        unsigned int size = 0;
565
 
566
        if (!buffer) {
567
                for_each_xattr_handler(handlers, handler)
568
                        size += handler->list(inode, NULL, 0, NULL, 0);
569
        } else {
570
                char *buf = buffer;
571
 
572
                for_each_xattr_handler(handlers, handler) {
573
                        size = handler->list(inode, buf, buffer_size, NULL, 0);
574
                        if (size > buffer_size)
575
                                return -ERANGE;
576
                        buf += size;
577
                        buffer_size -= size;
578
                }
579
                size = buf - buffer;
580
        }
581
        return size;
582
}
583
 
584
/*
585
 * Find the handler for the prefix and dispatch its set() operation.
586
 */
587
int
588
generic_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags)
589
{
590
        struct xattr_handler *handler;
591
        struct inode *inode = dentry->d_inode;
592
 
593
        if (size == 0)
594
                value = "";  /* empty EA, do not remove */
595
        handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
596
        if (!handler)
597
                return -EOPNOTSUPP;
598
        return handler->set(inode, name, value, size, flags);
599
}
600
 
601
/*
602
 * Find the handler for the prefix and dispatch its set() operation to remove
603
 * any associated extended attribute.
604
 */
605
int
606
generic_removexattr(struct dentry *dentry, const char *name)
607
{
608
        struct xattr_handler *handler;
609
        struct inode *inode = dentry->d_inode;
610
 
611
        handler = xattr_resolve_name(inode->i_sb->s_xattr, &name);
612
        if (!handler)
613
                return -EOPNOTSUPP;
614
        return handler->set(inode, name, NULL, 0, XATTR_REPLACE);
615
}
616
 
617
EXPORT_SYMBOL(generic_getxattr);
618
EXPORT_SYMBOL(generic_listxattr);
619
EXPORT_SYMBOL(generic_setxattr);
620
EXPORT_SYMBOL(generic_removexattr);

powered by: WebSVN 2.1.0

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