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