Revision 131dcb25
b/hw/file-op-9p.h | ||
---|---|---|
27 | 27 |
|
28 | 28 |
typedef struct FileOperations |
29 | 29 |
{ |
30 |
int (*lstat)(FsContext *, const char *, struct stat *); |
|
31 |
ssize_t (*readlink)(FsContext *, const char *, char *, size_t); |
|
32 |
int (*setuid)(FsContext *, uid_t); |
|
33 |
int (*close)(FsContext *, int); |
|
34 |
int (*closedir)(FsContext *, DIR *); |
|
30 | 35 |
void *opaque; |
31 | 36 |
} FileOperations; |
32 | 37 |
#endif |
b/hw/virtio-9p-local.c | ||
---|---|---|
12 | 12 |
*/ |
13 | 13 |
#include "virtio.h" |
14 | 14 |
#include "virtio-9p.h" |
15 |
#include <pwd.h> |
|
16 |
#include <grp.h> |
|
17 |
|
|
18 |
static const char *rpath(FsContext *ctx, const char *path) |
|
19 |
{ |
|
20 |
/* FIXME: so wrong... */ |
|
21 |
static char buffer[4096]; |
|
22 |
snprintf(buffer, sizeof(buffer), "%s/%s", ctx->fs_root, path); |
|
23 |
return buffer; |
|
24 |
} |
|
25 |
|
|
26 |
static int local_lstat(FsContext *ctx, const char *path, struct stat *stbuf) |
|
27 |
{ |
|
28 |
return lstat(rpath(ctx, path), stbuf); |
|
29 |
} |
|
30 |
|
|
31 |
static int local_setuid(FsContext *ctx, uid_t uid) |
|
32 |
{ |
|
33 |
struct passwd *pw; |
|
34 |
gid_t groups[33]; |
|
35 |
int ngroups; |
|
36 |
static uid_t cur_uid = -1; |
|
37 |
|
|
38 |
if (cur_uid == uid) { |
|
39 |
return 0; |
|
40 |
} |
|
41 |
|
|
42 |
if (setreuid(0, 0)) { |
|
43 |
return -1; |
|
44 |
} |
|
45 |
|
|
46 |
pw = getpwuid(uid); |
|
47 |
if (pw == NULL) { |
|
48 |
return -1; |
|
49 |
} |
|
50 |
|
|
51 |
ngroups = 33; |
|
52 |
if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups) == -1) { |
|
53 |
return -1; |
|
54 |
} |
|
55 |
|
|
56 |
if (setgroups(ngroups, groups)) { |
|
57 |
return -1; |
|
58 |
} |
|
59 |
|
|
60 |
if (setregid(-1, pw->pw_gid)) { |
|
61 |
return -1; |
|
62 |
} |
|
63 |
|
|
64 |
if (setreuid(-1, uid)) { |
|
65 |
return -1; |
|
66 |
} |
|
67 |
|
|
68 |
cur_uid = uid; |
|
69 |
|
|
70 |
return 0; |
|
71 |
} |
|
72 |
|
|
73 |
static ssize_t local_readlink(FsContext *ctx, const char *path, |
|
74 |
char *buf, size_t bufsz) |
|
75 |
{ |
|
76 |
return readlink(rpath(ctx, path), buf, bufsz); |
|
77 |
} |
|
78 |
|
|
79 |
static int local_close(FsContext *ctx, int fd) |
|
80 |
{ |
|
81 |
return close(fd); |
|
82 |
} |
|
83 |
|
|
84 |
static int local_closedir(FsContext *ctx, DIR *dir) |
|
85 |
{ |
|
86 |
return closedir(dir); |
|
87 |
} |
|
15 | 88 |
|
16 | 89 |
FileOperations local_ops = { |
90 |
.lstat = local_lstat, |
|
91 |
.setuid = local_setuid, |
|
92 |
.readlink = local_readlink, |
|
93 |
.close = local_close, |
|
94 |
.closedir = local_closedir, |
|
17 | 95 |
}; |
b/hw/virtio-9p.c | ||
---|---|---|
21 | 21 |
int dotu = 1; |
22 | 22 |
int debug_9p_pdu; |
23 | 23 |
|
24 |
static int v9fs_do_lstat(V9fsState *s, V9fsString *path, struct stat *stbuf) |
|
25 |
{ |
|
26 |
return s->ops->lstat(&s->ctx, path->data, stbuf); |
|
27 |
} |
|
28 |
|
|
29 |
static int v9fs_do_setuid(V9fsState *s, uid_t uid) |
|
30 |
{ |
|
31 |
return s->ops->setuid(&s->ctx, uid); |
|
32 |
} |
|
33 |
|
|
34 |
static ssize_t v9fs_do_readlink(V9fsState *s, V9fsString *path, V9fsString *buf) |
|
35 |
{ |
|
36 |
ssize_t len; |
|
37 |
|
|
38 |
buf->data = qemu_malloc(1024); |
|
39 |
|
|
40 |
len = s->ops->readlink(&s->ctx, path->data, buf->data, 1024 - 1); |
|
41 |
if (len > -1) { |
|
42 |
buf->size = len; |
|
43 |
buf->data[len] = 0; |
|
44 |
} |
|
45 |
|
|
46 |
return len; |
|
47 |
} |
|
48 |
|
|
49 |
static int v9fs_do_close(V9fsState *s, int fd) |
|
50 |
{ |
|
51 |
return s->ops->close(&s->ctx, fd); |
|
52 |
} |
|
53 |
|
|
54 |
static int v9fs_do_closedir(V9fsState *s, DIR *dir) |
|
55 |
{ |
|
56 |
return s->ops->closedir(&s->ctx, dir); |
|
57 |
} |
|
58 |
|
|
24 | 59 |
static void v9fs_string_init(V9fsString *str) |
25 | 60 |
{ |
26 | 61 |
str->data = NULL; |
... | ... | |
437 | 472 |
(void) v9fs_string_sprintf; |
438 | 473 |
(void) v9fs_string_copy; |
439 | 474 |
(void) v9fs_string_size; |
440 |
|
|
441 |
|
|
475 |
(void) v9fs_do_lstat; |
|
476 |
(void) v9fs_do_setuid; |
|
477 |
(void) v9fs_do_readlink; |
|
478 |
(void) v9fs_do_close; |
|
479 |
(void) v9fs_do_closedir; |
|
442 | 480 |
} |
481 |
|
|
443 | 482 |
static void v9fs_version(V9fsState *s, V9fsPDU *pdu) |
444 | 483 |
{ |
445 | 484 |
if (debug_9p_pdu) { |
Also available in: Unified diff