Revision fc22118d

b/Makefile.objs
249 249
adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
250 250
hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
251 251

  
252
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-debug.o virtio-9p-local.o
252
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-debug.o virtio-9p-local.o virtio-9p-xattr.o
253
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o
253 254

  
254 255
######################################################################
255 256
# libdis
b/hw/file-op-9p.h
47 47
    dev_t   fc_rdev;
48 48
} FsCred;
49 49

  
50
struct xattr_operations;
51

  
50 52
typedef struct FsContext
51 53
{
52 54
    char *fs_root;
53 55
    SecModel fs_sm;
54 56
    uid_t uid;
57
    struct xattr_operations **xops;
55 58
} FsContext;
56 59

  
57 60
extern void cred_init(FsCred *);
......
94 97
    int (*lremovexattr)(FsContext *, const char *, const char *);
95 98
    void *opaque;
96 99
} FileOperations;
100

  
101
static inline const char *rpath(FsContext *ctx, const char *path)
102
{
103
    /* FIXME: so wrong... */
104
    static char buffer[4096];
105
    snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
106
    return buffer;
107
}
97 108
#endif
b/hw/virtio-9p-local.c
12 12
 */
13 13
#include "virtio.h"
14 14
#include "virtio-9p.h"
15
#include "virtio-9p-xattr.h"
15 16
#include <arpa/inet.h>
16 17
#include <pwd.h>
17 18
#include <grp.h>
......
19 20
#include <sys/un.h>
20 21
#include <attr/xattr.h>
21 22

  
22
static const char *rpath(FsContext *ctx, const char *path)
23
{
24
    /* FIXME: so wrong... */
25
    static char buffer[4096];
26
    snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path);
27
    return buffer;
28
}
29

  
30 23

  
31 24
static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
32 25
{
......
497 490
static ssize_t local_lgetxattr(FsContext *ctx, const char *path,
498 491
                               const char *name, void *value, size_t size)
499 492
{
500
    if ((ctx->fs_sm == SM_MAPPED) &&
501
        (strncmp(name, "user.virtfs.", 12) == 0)) {
502
        /*
503
         * Don't allow fetch of user.virtfs namesapce
504
         * in case of mapped security
505
         */
506
        errno = ENOATTR;
507
        return -1;
508
    }
509

  
510
    return lgetxattr(rpath(ctx, path), name, value, size);
493
    return v9fs_get_xattr(ctx, path, name, value, size);
511 494
}
512 495

  
513 496
static ssize_t local_llistxattr(FsContext *ctx, const char *path,
514 497
                                void *value, size_t size)
515 498
{
516
    ssize_t retval;
517
    ssize_t actual_len = 0;
518
    char *orig_value, *orig_value_start;
519
    char *temp_value, *temp_value_start;
520
    ssize_t xattr_len, parsed_len = 0, attr_len;
521

  
522
    if (ctx->fs_sm != SM_MAPPED) {
523
        return llistxattr(rpath(ctx, path), value, size);
524
    }
525

  
526
    /* Get the actual len */
527
    xattr_len = llistxattr(rpath(ctx, path), value, 0);
528

  
529
    /* Now fetch the xattr and find the actual size */
530
    orig_value = qemu_malloc(xattr_len);
531
    xattr_len = llistxattr(rpath(ctx, path), orig_value, xattr_len);
532

  
533
    /*
534
     * For mapped security model drop user.virtfs namespace
535
     * from the list
536
     */
537
    temp_value = qemu_mallocz(xattr_len);
538
    temp_value_start = temp_value;
539
    orig_value_start = orig_value;
540
    while (xattr_len > parsed_len) {
541
        attr_len = strlen(orig_value) + 1;
542
        if (strncmp(orig_value, "user.virtfs.", 12) != 0) {
543
            /* Copy this entry */
544
            strcat(temp_value, orig_value);
545
            temp_value  += attr_len;
546
            actual_len += attr_len;
547
        }
548
        parsed_len += attr_len;
549
        orig_value += attr_len;
550
    }
551
    if (!size) {
552
        retval = actual_len;
553
        goto out;
554
    } else if (size >= actual_len) {
555
        /* now copy the parsed attribute list back */
556
        memset(value, 0, size);
557
        memcpy(value, temp_value_start, actual_len);
558
        retval = actual_len;
559
        goto out;
560
    }
561
    errno = ERANGE;
562
    retval = -1;
563
out:
564
    qemu_free(orig_value_start);
565
    qemu_free(temp_value_start);
566
    return retval;
499
    return v9fs_list_xattr(ctx, path, value, size);
567 500
}
568 501

  
569 502
static int local_lsetxattr(FsContext *ctx, const char *path, const char *name,
570 503
                           void *value, size_t size, int flags)
571 504
{
572
    if ((ctx->fs_sm == SM_MAPPED) &&
573
        (strncmp(name, "user.virtfs.", 12) == 0)) {
574
        /*
575
         * Don't allow fetch of user.virtfs namesapce
576
         * in case of mapped security
577
         */
578
        errno = EACCES;
579
        return -1;
580
    }
581
    return lsetxattr(rpath(ctx, path), name, value, size, flags);
505
    return v9fs_set_xattr(ctx, path, name, value, size, flags);
582 506
}
583 507

  
584 508
static int local_lremovexattr(FsContext *ctx,
585 509
                              const char *path, const char *name)
586 510
{
587
    if ((ctx->fs_sm == SM_MAPPED) &&
588
        (strncmp(name, "user.virtfs.", 12) == 0)) {
589
        /*
590
         * Don't allow fetch of user.virtfs namesapce
591
         * in case of mapped security
592
         */
593
        errno = EACCES;
594
        return -1;
595
    }
596
    return lremovexattr(rpath(ctx, path), name);
511
    return v9fs_remove_xattr(ctx, path, name);
597 512
}
598 513

  
599 514

  
b/hw/virtio-9p-xattr-user.c
1
/*
2
 * Virtio 9p user. xattr callback
3
 *
4
 * Copyright IBM, Corp. 2010
5
 *
6
 * Authors:
7
 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10
 * the COPYING file in the top-level directory.
11
 *
12
 */
13

  
14
#include <sys/types.h>
15
#include "virtio.h"
16
#include "virtio-9p.h"
17
#include "file-op-9p.h"
18
#include "virtio-9p-xattr.h"
19

  
20

  
21
static ssize_t mp_user_getxattr(FsContext *ctx, const char *path,
22
                                const char *name, void *value, size_t size)
23
{
24
    if (strncmp(name, "user.virtfs.", 12) == 0) {
25
        /*
26
         * Don't allow fetch of user.virtfs namesapce
27
         * in case of mapped security
28
         */
29
        errno = ENOATTR;
30
        return -1;
31
    }
32
    return lgetxattr(rpath(ctx, path), name, value, size);
33
}
34

  
35
static ssize_t mp_user_listxattr(FsContext *ctx, const char *path,
36
                                 char *name, void *value, size_t size)
37
{
38
    int name_size = strlen(name) + 1;
39
    if (strncmp(name, "user.virtfs.", 12) == 0) {
40
        /*
41
         * Don't allow fetch of user.virtfs namesapce
42
         * in case of mapped security
43
         */
44
        return 0;
45
    }
46
    if (!value) {
47
        return name_size;
48
    }
49

  
50
    if (size < name_size) {
51
        errno = ERANGE;
52
        return -1;
53
    }
54

  
55
    strncpy(value, name, name_size);
56
    return name_size;
57
}
58

  
59
static int mp_user_setxattr(FsContext *ctx, const char *path, const char *name,
60
                            void *value, size_t size, int flags)
61
{
62
    if (strncmp(name, "user.virtfs.", 12) == 0) {
63
        /*
64
         * Don't allow fetch of user.virtfs namesapce
65
         * in case of mapped security
66
         */
67
        errno = EACCES;
68
        return -1;
69
    }
70
    return lsetxattr(rpath(ctx, path), name, value, size, flags);
71
}
72

  
73
static int mp_user_removexattr(FsContext *ctx,
74
                               const char *path, const char *name)
75
{
76
    if (strncmp(name, "user.virtfs.", 12) == 0) {
77
        /*
78
         * Don't allow fetch of user.virtfs namesapce
79
         * in case of mapped security
80
         */
81
        errno = EACCES;
82
        return -1;
83
    }
84
    return lremovexattr(rpath(ctx, path), name);
85
}
86

  
87
XattrOperations mapped_user_xattr = {
88
    .name = "user.",
89
    .getxattr = mp_user_getxattr,
90
    .setxattr = mp_user_setxattr,
91
    .listxattr = mp_user_listxattr,
92
    .removexattr = mp_user_removexattr,
93
};
94

  
95
XattrOperations passthrough_user_xattr = {
96
    .name = "user.",
97
    .getxattr = pt_getxattr,
98
    .setxattr = pt_setxattr,
99
    .listxattr = pt_listxattr,
100
    .removexattr = pt_removexattr,
101
};
b/hw/virtio-9p-xattr.c
1
/*
2
 * Virtio 9p  xattr callback
3
 *
4
 * Copyright IBM, Corp. 2010
5
 *
6
 * Authors:
7
 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10
 * the COPYING file in the top-level directory.
11
 *
12
 */
13

  
14
#include "virtio.h"
15
#include "virtio-9p.h"
16
#include "file-op-9p.h"
17
#include "virtio-9p-xattr.h"
18

  
19

  
20
static XattrOperations *get_xattr_operations(XattrOperations **h,
21
                                             const char *name)
22
{
23
    XattrOperations *xops;
24
    for (xops = *(h)++; xops != NULL; xops = *(h)++) {
25
        if (!strncmp(name, xops->name, strlen(xops->name))) {
26
            return xops;
27
        }
28
    }
29
    return NULL;
30
}
31

  
32
ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
33
                       const char *name, void *value, size_t size)
34
{
35
    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
36
    if (xops) {
37
        return xops->getxattr(ctx, path, name, value, size);
38
    }
39
    errno = -EOPNOTSUPP;
40
    return -1;
41
}
42

  
43
ssize_t pt_listxattr(FsContext *ctx, const char *path,
44
                     char *name, void *value, size_t size)
45
{
46
    int name_size = strlen(name) + 1;
47
    if (!value) {
48
        return name_size;
49
    }
50

  
51
    if (size < name_size) {
52
        errno = ERANGE;
53
        return -1;
54
    }
55

  
56
    strncpy(value, name, name_size);
57
    return name_size;
58
}
59

  
60

  
61
/*
62
 * Get the list and pass to each layer to find out whether
63
 * to send the data or not
64
 */
65
ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
66
                        void *value, size_t vsize)
67
{
68
    ssize_t size = 0;
69
    void *ovalue = value;
70
    XattrOperations *xops;
71
    char *orig_value, *orig_value_start;
72
    ssize_t xattr_len, parsed_len = 0, attr_len;
73

  
74
    /* Get the actual len */
75
    xattr_len = llistxattr(rpath(ctx, path), value, 0);
76

  
77
    /* Now fetch the xattr and find the actual size */
78
    orig_value = qemu_malloc(xattr_len);
79
    xattr_len = llistxattr(rpath(ctx, path), orig_value, xattr_len);
80

  
81
    /* store the orig pointer */
82
    orig_value_start = orig_value;
83
    while (xattr_len > parsed_len) {
84
        xops = get_xattr_operations(ctx->xops, orig_value);
85
        if (!xops) {
86
            goto next_entry;
87
        }
88

  
89
        if (!value) {
90
            size += xops->listxattr(ctx, path, orig_value, value, vsize);
91
        } else {
92
            size = xops->listxattr(ctx, path, orig_value, value, vsize);
93
            if (size < 0) {
94
                goto err_out;
95
            }
96
            value += size;
97
            vsize -= size;
98
        }
99
next_entry:
100
        /* Got the next entry */
101
        attr_len = strlen(orig_value) + 1;
102
        parsed_len += attr_len;
103
        orig_value += attr_len;
104
    }
105
    if (value) {
106
        size = value - ovalue;
107
    }
108

  
109
err_out:
110
    qemu_free(orig_value_start);
111
    return size;
112
}
113

  
114
int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
115
                   void *value, size_t size, int flags)
116
{
117
    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
118
    if (xops) {
119
        return xops->setxattr(ctx, path, name, value, size, flags);
120
    }
121
    errno = -EOPNOTSUPP;
122
    return -1;
123

  
124
}
125

  
126
int v9fs_remove_xattr(FsContext *ctx,
127
                      const char *path, const char *name)
128
{
129
    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
130
    if (xops) {
131
        return xops->removexattr(ctx, path, name);
132
    }
133
    errno = -EOPNOTSUPP;
134
    return -1;
135

  
136
}
137

  
138
XattrOperations *mapped_xattr_ops[] = {
139
    &mapped_user_xattr,
140
    NULL,
141
};
142

  
143
XattrOperations *passthrough_xattr_ops[] = {
144
    &passthrough_user_xattr,
145
    NULL,
146
};
147

  
148
/* for .user none model should be same as passthrough */
149
XattrOperations *none_xattr_ops[] = {
150
    &passthrough_user_xattr,
151
    NULL,
152
};
b/hw/virtio-9p-xattr.h
1
/*
2
 * Virtio 9p
3
 *
4
 * Copyright IBM, Corp. 2010
5
 *
6
 * Authors:
7
 *  Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
8
 *
9
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10
 * the COPYING file in the top-level directory.
11
 *
12
 */
13
#ifndef _QEMU_VIRTIO_9P_XATTR_H
14
#define _QEMU_VIRTIO_9P_XATTR_H
15

  
16
#include <attr/xattr.h>
17

  
18
typedef struct xattr_operations
19
{
20
    const char *name;
21
    ssize_t (*getxattr)(FsContext *ctx, const char *path,
22
                        const char *name, void *value, size_t size);
23
    ssize_t (*listxattr)(FsContext *ctx, const char *path,
24
                         char *name, void *value, size_t size);
25
    int (*setxattr)(FsContext *ctx, const char *path, const char *name,
26
                    void *value, size_t size, int flags);
27
    int (*removexattr)(FsContext *ctx,
28
                       const char *path, const char *name);
29
} XattrOperations;
30

  
31

  
32
extern XattrOperations mapped_user_xattr;
33
extern XattrOperations passthrough_user_xattr;
34

  
35
extern XattrOperations *mapped_xattr_ops[];
36
extern XattrOperations *passthrough_xattr_ops[];
37
extern XattrOperations *none_xattr_ops[];
38

  
39
extern ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
40
                              const char *name, void *value, size_t size);
41
extern ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
42
                               void *value, size_t vsize);
43
extern int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
44
                          void *value, size_t size, int flags);
45
extern int v9fs_remove_xattr(FsContext *ctx,
46
                             const char *path, const char *name);
47
extern ssize_t pt_listxattr(FsContext *ctx, const char *path,
48
                            char *name, void *value, size_t size);
49

  
50
static inline ssize_t pt_getxattr(FsContext *ctx, const char *path,
51
                                  const char *name, void *value, size_t size)
52
{
53
    return lgetxattr(rpath(ctx, path), name, value, size);
54
}
55

  
56
static inline int pt_setxattr(FsContext *ctx, const char *path,
57
                              const char *name, void *value,
58
                              size_t size, int flags)
59
{
60
    return lsetxattr(rpath(ctx, path), name, value, size, flags);
61
}
62

  
63
static inline int pt_removexattr(FsContext *ctx,
64
                                 const char *path, const char *name)
65
{
66
    return lremovexattr(rpath(ctx, path), name);
67
}
68

  
69
#endif
b/hw/virtio-9p.c
17 17
#include "virtio-9p.h"
18 18
#include "fsdev/qemu-fsdev.h"
19 19
#include "virtio-9p-debug.h"
20
#include "virtio-9p-xattr.h"
20 21

  
21 22
int debug_9p_pdu;
22 23

  
......
3712 3713
    if (!strcmp(fse->security_model, "passthrough")) {
3713 3714
        /* Files on the Fileserver set to client user credentials */
3714 3715
        s->ctx.fs_sm = SM_PASSTHROUGH;
3716
        s->ctx.xops = passthrough_xattr_ops;
3715 3717
    } else if (!strcmp(fse->security_model, "mapped")) {
3716 3718
        /* Files on the fileserver are set to QEMU credentials.
3717 3719
         * Client user credentials are saved in extended attributes.
3718 3720
         */
3719 3721
        s->ctx.fs_sm = SM_MAPPED;
3722
        s->ctx.xops = mapped_xattr_ops;
3720 3723
    } else if (!strcmp(fse->security_model, "none")) {
3721 3724
        /*
3722 3725
         * Files on the fileserver are set to QEMU credentials.
3723 3726
         */
3724 3727
        s->ctx.fs_sm = SM_NONE;
3725

  
3728
        s->ctx.xops = none_xattr_ops;
3726 3729
    } else {
3727 3730
        fprintf(stderr, "Default to security_model=none. You may want"
3728 3731
                " enable advanced security model using "
3729 3732
                "security option:\n\t security_model=passthrough \n\t "
3730 3733
                "security_model=mapped\n");
3731 3734
        s->ctx.fs_sm = SM_NONE;
3735
        s->ctx.xops = none_xattr_ops;
3732 3736
    }
3733 3737

  
3734 3738
    if (lstat(fse->path, &stat)) {

Also available in: Unified diff