Revision 879c2813
b/hw/file-op-9p.h | ||
---|---|---|
55 | 55 |
int (*mksock)(FsContext *, const char *); |
56 | 56 |
int (*utime)(FsContext *, const char *, const struct utimbuf *); |
57 | 57 |
int (*remove)(FsContext *, const char *); |
58 |
int (*symlink)(FsContext *, const char *, const char *); |
|
58 |
int (*symlink)(FsContext *, const char *, const char *, FsCred *);
|
|
59 | 59 |
int (*link)(FsContext *, const char *, const char *); |
60 | 60 |
int (*setuid)(FsContext *, uid_t); |
61 | 61 |
int (*close)(FsContext *, int); |
b/hw/virtio-9p-local.c | ||
---|---|---|
107 | 107 |
return 0; |
108 | 108 |
} |
109 | 109 |
|
110 |
static ssize_t local_readlink(FsContext *ctx, const char *path, |
|
111 |
char *buf, size_t bufsz)
|
|
110 |
static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
|
|
111 |
char *buf, size_t bufsz) |
|
112 | 112 |
{ |
113 |
return readlink(rpath(ctx, path), buf, bufsz); |
|
113 |
ssize_t tsize = -1; |
|
114 |
if (fs_ctx->fs_sm == SM_MAPPED) { |
|
115 |
int fd; |
|
116 |
fd = open(rpath(fs_ctx, path), O_RDONLY); |
|
117 |
if (fd == -1) { |
|
118 |
return -1; |
|
119 |
} |
|
120 |
do { |
|
121 |
tsize = read(fd, (void *)buf, bufsz); |
|
122 |
} while (tsize == -1 && errno == EINTR); |
|
123 |
close(fd); |
|
124 |
return tsize; |
|
125 |
} else if (fs_ctx->fs_sm == SM_PASSTHROUGH) { |
|
126 |
tsize = readlink(rpath(fs_ctx, path), buf, bufsz); |
|
127 |
} |
|
128 |
return tsize; |
|
114 | 129 |
} |
115 | 130 |
|
116 | 131 |
static int local_close(FsContext *ctx, int fd) |
... | ... | |
314 | 329 |
} |
315 | 330 |
|
316 | 331 |
|
317 |
static int local_symlink(FsContext *ctx, const char *oldpath, |
|
318 |
const char *newpath)
|
|
332 |
static int local_symlink(FsContext *fs_ctx, const char *oldpath,
|
|
333 |
const char *newpath, FsCred *credp)
|
|
319 | 334 |
{ |
320 |
return symlink(oldpath, rpath(ctx, newpath)); |
|
335 |
int err = -1; |
|
336 |
int serrno = 0; |
|
337 |
|
|
338 |
/* Determine the security model */ |
|
339 |
if (fs_ctx->fs_sm == SM_MAPPED) { |
|
340 |
int fd; |
|
341 |
ssize_t oldpath_size, write_size; |
|
342 |
fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR, |
|
343 |
SM_LOCAL_MODE_BITS); |
|
344 |
if (fd == -1) { |
|
345 |
return fd; |
|
346 |
} |
|
347 |
/* Write the oldpath (target) to the file. */ |
|
348 |
oldpath_size = strlen(oldpath) + 1; |
|
349 |
do { |
|
350 |
write_size = write(fd, (void *)oldpath, oldpath_size); |
|
351 |
} while (write_size == -1 && errno == EINTR); |
|
352 |
|
|
353 |
if (write_size != oldpath_size) { |
|
354 |
serrno = errno; |
|
355 |
close(fd); |
|
356 |
err = -1; |
|
357 |
goto err_end; |
|
358 |
} |
|
359 |
close(fd); |
|
360 |
/* Set cleint credentials in symlink's xattr */ |
|
361 |
credp->fc_mode = credp->fc_mode|S_IFLNK; |
|
362 |
err = local_set_xattr(rpath(fs_ctx, newpath), credp); |
|
363 |
if (err == -1) { |
|
364 |
serrno = errno; |
|
365 |
goto err_end; |
|
366 |
} |
|
367 |
} else if (fs_ctx->fs_sm == SM_PASSTHROUGH) { |
|
368 |
err = symlink(oldpath, rpath(fs_ctx, newpath)); |
|
369 |
if (err) { |
|
370 |
return err; |
|
371 |
} |
|
372 |
err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid); |
|
373 |
if (err == -1) { |
|
374 |
serrno = errno; |
|
375 |
goto err_end; |
|
376 |
} |
|
377 |
} |
|
378 |
return err; |
|
379 |
|
|
380 |
err_end: |
|
381 |
remove(rpath(fs_ctx, newpath)); |
|
382 |
errno = serrno; |
|
383 |
return err; |
|
321 | 384 |
} |
322 | 385 |
|
323 | 386 |
static int local_link(FsContext *ctx, const char *oldpath, const char *newpath) |
b/hw/virtio-9p.c | ||
---|---|---|
199 | 199 |
return s->ops->open2(&s->ctx, vs->fullname.data, flags, &cred); |
200 | 200 |
} |
201 | 201 |
|
202 |
static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath, |
|
203 |
V9fsString *newpath) |
|
202 |
static int v9fs_do_symlink(V9fsState *s, V9fsCreateState *vs) |
|
204 | 203 |
{ |
205 |
return s->ops->symlink(&s->ctx, oldpath->data, newpath->data); |
|
204 |
FsCred cred; |
|
205 |
cred_init(&cred); |
|
206 |
cred.fc_uid = vs->fidp->uid; |
|
207 |
cred.fc_mode = vs->perm | 0777; |
|
208 |
|
|
209 |
return s->ops->symlink(&s->ctx, vs->extension.data, vs->fullname.data, |
|
210 |
&cred); |
|
206 | 211 |
} |
207 | 212 |
|
208 | 213 |
static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) |
... | ... | |
1785 | 1790 |
err = v9fs_do_mkdir(s, vs); |
1786 | 1791 |
v9fs_create_post_mkdir(s, vs, err); |
1787 | 1792 |
} else if (vs->perm & P9_STAT_MODE_SYMLINK) { |
1788 |
err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
|
|
1793 |
err = v9fs_do_symlink(s, vs);
|
|
1789 | 1794 |
v9fs_create_post_perms(s, vs, err); |
1790 | 1795 |
} else if (vs->perm & P9_STAT_MODE_LINK) { |
1791 | 1796 |
int32_t nfid = atoi(vs->extension.data); |
Also available in: Unified diff