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