Annotation of qemu/hw/virtio-9p-local.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Virtio 9p Posix callback
                      3:  *
                      4:  * Copyright IBM, Corp. 2010
                      5:  *
                      6:  * Authors:
                      7:  *  Anthony Liguori   <[email protected]>
                      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: #include "virtio.h"
                     14: #include "virtio-9p.h"
1.1.1.2 ! root       15: #include "virtio-9p-xattr.h"
1.1       root       16: #include <arpa/inet.h>
                     17: #include <pwd.h>
                     18: #include <grp.h>
                     19: #include <sys/socket.h>
                     20: #include <sys/un.h>
                     21: #include <attr/xattr.h>
                     22: 
                     23: 
                     24: static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
                     25: {
                     26:     int err;
                     27:     err =  lstat(rpath(fs_ctx, path), stbuf);
                     28:     if (err) {
                     29:         return err;
                     30:     }
                     31:     if (fs_ctx->fs_sm == SM_MAPPED) {
                     32:         /* Actual credentials are part of extended attrs */
                     33:         uid_t tmp_uid;
                     34:         gid_t tmp_gid;
                     35:         mode_t tmp_mode;
                     36:         dev_t tmp_dev;
                     37:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid,
                     38:                     sizeof(uid_t)) > 0) {
                     39:             stbuf->st_uid = tmp_uid;
                     40:         }
                     41:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid,
                     42:                     sizeof(gid_t)) > 0) {
                     43:             stbuf->st_gid = tmp_gid;
                     44:         }
                     45:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode,
                     46:                     sizeof(mode_t)) > 0) {
                     47:             stbuf->st_mode = tmp_mode;
                     48:         }
                     49:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
                     50:                         sizeof(dev_t)) > 0) {
                     51:                 stbuf->st_rdev = tmp_dev;
                     52:         }
                     53:     }
                     54:     return err;
                     55: }
                     56: 
                     57: static int local_set_xattr(const char *path, FsCred *credp)
                     58: {
                     59:     int err;
                     60:     if (credp->fc_uid != -1) {
                     61:         err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
                     62:                 0);
                     63:         if (err) {
                     64:             return err;
                     65:         }
                     66:     }
                     67:     if (credp->fc_gid != -1) {
                     68:         err = setxattr(path, "user.virtfs.gid", &credp->fc_gid, sizeof(gid_t),
                     69:                 0);
                     70:         if (err) {
                     71:             return err;
                     72:         }
                     73:     }
                     74:     if (credp->fc_mode != -1) {
                     75:         err = setxattr(path, "user.virtfs.mode", &credp->fc_mode,
                     76:                 sizeof(mode_t), 0);
                     77:         if (err) {
                     78:             return err;
                     79:         }
                     80:     }
                     81:     if (credp->fc_rdev != -1) {
                     82:         err = setxattr(path, "user.virtfs.rdev", &credp->fc_rdev,
                     83:                 sizeof(dev_t), 0);
                     84:         if (err) {
                     85:             return err;
                     86:         }
                     87:     }
                     88:     return 0;
                     89: }
                     90: 
                     91: static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
                     92:         FsCred *credp)
                     93: {
                     94:     if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) {
                     95:         return -1;
                     96:     }
1.1.1.2 ! root       97:     if (lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid) < 0) {
        !            98:         /*
        !            99:          * If we fail to change ownership and if we are
        !           100:          * using security model none. Ignore the error
        !           101:          */
        !           102:         if (fs_ctx->fs_sm != SM_NONE) {
        !           103:             return -1;
        !           104:         }
1.1       root      105:     }
                    106:     return 0;
                    107: }
                    108: 
                    109: static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
                    110:         char *buf, size_t bufsz)
                    111: {
                    112:     ssize_t tsize = -1;
                    113:     if (fs_ctx->fs_sm == SM_MAPPED) {
                    114:         int fd;
                    115:         fd = open(rpath(fs_ctx, path), O_RDONLY);
                    116:         if (fd == -1) {
                    117:             return -1;
                    118:         }
                    119:         do {
                    120:             tsize = read(fd, (void *)buf, bufsz);
                    121:         } while (tsize == -1 && errno == EINTR);
                    122:         close(fd);
                    123:         return tsize;
1.1.1.2 ! root      124:     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
        !           125:                (fs_ctx->fs_sm == SM_NONE)) {
1.1       root      126:         tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
                    127:     }
                    128:     return tsize;
                    129: }
                    130: 
                    131: static int local_close(FsContext *ctx, int fd)
                    132: {
                    133:     return close(fd);
                    134: }
                    135: 
                    136: static int local_closedir(FsContext *ctx, DIR *dir)
                    137: {
                    138:     return closedir(dir);
                    139: }
                    140: 
                    141: static int local_open(FsContext *ctx, const char *path, int flags)
                    142: {
                    143:     return open(rpath(ctx, path), flags);
                    144: }
                    145: 
                    146: static DIR *local_opendir(FsContext *ctx, const char *path)
                    147: {
                    148:     return opendir(rpath(ctx, path));
                    149: }
                    150: 
                    151: static void local_rewinddir(FsContext *ctx, DIR *dir)
                    152: {
                    153:     return rewinddir(dir);
                    154: }
                    155: 
                    156: static off_t local_telldir(FsContext *ctx, DIR *dir)
                    157: {
                    158:     return telldir(dir);
                    159: }
                    160: 
                    161: static struct dirent *local_readdir(FsContext *ctx, DIR *dir)
                    162: {
                    163:     return readdir(dir);
                    164: }
                    165: 
                    166: static void local_seekdir(FsContext *ctx, DIR *dir, off_t off)
                    167: {
                    168:     return seekdir(dir, off);
                    169: }
                    170: 
1.1.1.2 ! root      171: static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov,
        !           172:                             int iovcnt, off_t offset)
1.1       root      173: {
1.1.1.2 ! root      174: #ifdef CONFIG_PREADV
        !           175:     return preadv(fd, iov, iovcnt, offset);
        !           176: #else
        !           177:     int err = lseek(fd, offset, SEEK_SET);
        !           178:     if (err == -1) {
        !           179:         return err;
        !           180:     } else {
        !           181:         return readv(fd, iov, iovcnt);
        !           182:     }
        !           183: #endif
1.1       root      184: }
                    185: 
1.1.1.2 ! root      186: static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov,
        !           187:                             int iovcnt, off_t offset)
1.1       root      188: {
1.1.1.2 ! root      189: #ifdef CONFIG_PREADV
        !           190:     return pwritev(fd, iov, iovcnt, offset);
        !           191: #else
        !           192:     int err = lseek(fd, offset, SEEK_SET);
        !           193:     if (err == -1) {
        !           194:         return err;
        !           195:     } else {
        !           196:         return writev(fd, iov, iovcnt);
        !           197:     }
        !           198: #endif
1.1       root      199: }
                    200: 
                    201: static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
                    202: {
                    203:     if (fs_ctx->fs_sm == SM_MAPPED) {
                    204:         return local_set_xattr(rpath(fs_ctx, path), credp);
1.1.1.2 ! root      205:     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
        !           206:                (fs_ctx->fs_sm == SM_NONE)) {
1.1       root      207:         return chmod(rpath(fs_ctx, path), credp->fc_mode);
                    208:     }
                    209:     return -1;
                    210: }
                    211: 
                    212: static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
                    213: {
                    214:     int err = -1;
                    215:     int serrno = 0;
                    216: 
                    217:     /* Determine the security model */
                    218:     if (fs_ctx->fs_sm == SM_MAPPED) {
                    219:         err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0);
                    220:         if (err == -1) {
                    221:             return err;
                    222:         }
                    223:         local_set_xattr(rpath(fs_ctx, path), credp);
                    224:         if (err == -1) {
                    225:             serrno = errno;
                    226:             goto err_end;
                    227:         }
1.1.1.2 ! root      228:     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
        !           229:                (fs_ctx->fs_sm == SM_NONE)) {
1.1       root      230:         err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev);
                    231:         if (err == -1) {
                    232:             return err;
                    233:         }
                    234:         err = local_post_create_passthrough(fs_ctx, path, credp);
                    235:         if (err == -1) {
                    236:             serrno = errno;
                    237:             goto err_end;
                    238:         }
                    239:     }
                    240:     return err;
                    241: 
                    242: err_end:
                    243:     remove(rpath(fs_ctx, path));
                    244:     errno = serrno;
                    245:     return err;
                    246: }
                    247: 
                    248: static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
                    249: {
                    250:     int err = -1;
                    251:     int serrno = 0;
                    252: 
                    253:     /* Determine the security model */
                    254:     if (fs_ctx->fs_sm == SM_MAPPED) {
                    255:         err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS);
                    256:         if (err == -1) {
                    257:             return err;
                    258:         }
                    259:         credp->fc_mode = credp->fc_mode|S_IFDIR;
                    260:         err = local_set_xattr(rpath(fs_ctx, path), credp);
                    261:         if (err == -1) {
                    262:             serrno = errno;
                    263:             goto err_end;
                    264:         }
1.1.1.2 ! root      265:     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
        !           266:                (fs_ctx->fs_sm == SM_NONE)) {
1.1       root      267:         err = mkdir(rpath(fs_ctx, path), credp->fc_mode);
                    268:         if (err == -1) {
                    269:             return err;
                    270:         }
                    271:         err = local_post_create_passthrough(fs_ctx, path, credp);
                    272:         if (err == -1) {
                    273:             serrno = errno;
                    274:             goto err_end;
                    275:         }
                    276:     }
                    277:     return err;
                    278: 
                    279: err_end:
                    280:     remove(rpath(fs_ctx, path));
                    281:     errno = serrno;
                    282:     return err;
                    283: }
                    284: 
                    285: static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
                    286: {
                    287:     int err;
                    288:     err = fstat(fd, stbuf);
                    289:     if (err) {
                    290:         return err;
                    291:     }
                    292:     if (fs_ctx->fs_sm == SM_MAPPED) {
                    293:         /* Actual credentials are part of extended attrs */
                    294:         uid_t tmp_uid;
                    295:         gid_t tmp_gid;
                    296:         mode_t tmp_mode;
                    297:         dev_t tmp_dev;
                    298: 
                    299:         if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
                    300:             stbuf->st_uid = tmp_uid;
                    301:         }
                    302:         if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
                    303:             stbuf->st_gid = tmp_gid;
                    304:         }
                    305:         if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
                    306:             stbuf->st_mode = tmp_mode;
                    307:         }
                    308:         if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
                    309:                 stbuf->st_rdev = tmp_dev;
                    310:         }
                    311:     }
                    312:     return err;
                    313: }
                    314: 
                    315: static int local_open2(FsContext *fs_ctx, const char *path, int flags,
                    316:         FsCred *credp)
                    317: {
                    318:     int fd = -1;
                    319:     int err = -1;
                    320:     int serrno = 0;
                    321: 
                    322:     /* Determine the security model */
                    323:     if (fs_ctx->fs_sm == SM_MAPPED) {
                    324:         fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS);
                    325:         if (fd == -1) {
                    326:             return fd;
                    327:         }
                    328:         credp->fc_mode = credp->fc_mode|S_IFREG;
                    329:         /* Set cleint credentials in xattr */
                    330:         err = local_set_xattr(rpath(fs_ctx, path), credp);
                    331:         if (err == -1) {
                    332:             serrno = errno;
                    333:             goto err_end;
                    334:         }
1.1.1.2 ! root      335:     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
        !           336:                (fs_ctx->fs_sm == SM_NONE)) {
1.1       root      337:         fd = open(rpath(fs_ctx, path), flags, credp->fc_mode);
                    338:         if (fd == -1) {
                    339:             return fd;
                    340:         }
                    341:         err = local_post_create_passthrough(fs_ctx, path, credp);
                    342:         if (err == -1) {
                    343:             serrno = errno;
                    344:             goto err_end;
                    345:         }
                    346:     }
                    347:     return fd;
                    348: 
                    349: err_end:
                    350:     close(fd);
                    351:     remove(rpath(fs_ctx, path));
                    352:     errno = serrno;
                    353:     return err;
                    354: }
                    355: 
                    356: 
                    357: static int local_symlink(FsContext *fs_ctx, const char *oldpath,
                    358:         const char *newpath, FsCred *credp)
                    359: {
                    360:     int err = -1;
                    361:     int serrno = 0;
                    362: 
                    363:     /* Determine the security model */
                    364:     if (fs_ctx->fs_sm == SM_MAPPED) {
                    365:         int fd;
                    366:         ssize_t oldpath_size, write_size;
                    367:         fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
                    368:                 SM_LOCAL_MODE_BITS);
                    369:         if (fd == -1) {
                    370:             return fd;
                    371:         }
                    372:         /* Write the oldpath (target) to the file. */
                    373:         oldpath_size = strlen(oldpath) + 1;
                    374:         do {
                    375:             write_size = write(fd, (void *)oldpath, oldpath_size);
                    376:         } while (write_size == -1 && errno == EINTR);
                    377: 
                    378:         if (write_size != oldpath_size) {
                    379:             serrno = errno;
                    380:             close(fd);
                    381:             err = -1;
                    382:             goto err_end;
                    383:         }
                    384:         close(fd);
                    385:         /* Set cleint credentials in symlink's xattr */
                    386:         credp->fc_mode = credp->fc_mode|S_IFLNK;
                    387:         err = local_set_xattr(rpath(fs_ctx, newpath), credp);
                    388:         if (err == -1) {
                    389:             serrno = errno;
                    390:             goto err_end;
                    391:         }
1.1.1.2 ! root      392:     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
        !           393:                (fs_ctx->fs_sm == SM_NONE)) {
1.1       root      394:         err = symlink(oldpath, rpath(fs_ctx, newpath));
                    395:         if (err) {
                    396:             return err;
                    397:         }
                    398:         err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
                    399:         if (err == -1) {
1.1.1.2 ! root      400:             /*
        !           401:              * If we fail to change ownership and if we are
        !           402:              * using security model none. Ignore the error
        !           403:              */
        !           404:             if (fs_ctx->fs_sm != SM_NONE) {
        !           405:                 serrno = errno;
        !           406:                 goto err_end;
        !           407:             } else
        !           408:                 err = 0;
1.1       root      409:         }
                    410:     }
                    411:     return err;
                    412: 
                    413: err_end:
                    414:     remove(rpath(fs_ctx, newpath));
                    415:     errno = serrno;
                    416:     return err;
                    417: }
                    418: 
                    419: static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
                    420: {
                    421:     char *tmp = qemu_strdup(rpath(ctx, oldpath));
                    422:     int err, serrno = 0;
                    423: 
                    424:     if (tmp == NULL) {
                    425:         return -ENOMEM;
                    426:     }
                    427: 
                    428:     err = link(tmp, rpath(ctx, newpath));
                    429:     if (err == -1) {
                    430:         serrno = errno;
                    431:     }
                    432: 
                    433:     qemu_free(tmp);
                    434: 
                    435:     if (err == -1) {
                    436:         errno = serrno;
                    437:     }
                    438: 
                    439:     return err;
                    440: }
                    441: 
                    442: static int local_truncate(FsContext *ctx, const char *path, off_t size)
                    443: {
                    444:     return truncate(rpath(ctx, path), size);
                    445: }
                    446: 
                    447: static int local_rename(FsContext *ctx, const char *oldpath,
                    448:                         const char *newpath)
                    449: {
                    450:     char *tmp;
                    451:     int err;
                    452: 
                    453:     tmp = qemu_strdup(rpath(ctx, oldpath));
                    454: 
                    455:     err = rename(tmp, rpath(ctx, newpath));
                    456:     if (err == -1) {
                    457:         int serrno = errno;
                    458:         qemu_free(tmp);
                    459:         errno = serrno;
                    460:     } else {
                    461:         qemu_free(tmp);
                    462:     }
                    463: 
                    464:     return err;
                    465: 
                    466: }
                    467: 
                    468: static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
                    469: {
1.1.1.2 ! root      470:     if ((credp->fc_uid == -1 && credp->fc_gid == -1) ||
        !           471:             (fs_ctx->fs_sm == SM_PASSTHROUGH)) {
        !           472:         return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
        !           473:     } else if (fs_ctx->fs_sm == SM_MAPPED) {
1.1       root      474:         return local_set_xattr(rpath(fs_ctx, path), credp);
1.1.1.2 ! root      475:     } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) ||
        !           476:                (fs_ctx->fs_sm == SM_NONE)) {
1.1       root      477:         return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
                    478:     }
                    479:     return -1;
                    480: }
                    481: 
1.1.1.2 ! root      482: static int local_utimensat(FsContext *s, const char *path,
        !           483:                            const struct timespec *buf)
1.1       root      484: {
1.1.1.2 ! root      485:     return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW);
1.1       root      486: }
                    487: 
                    488: static int local_remove(FsContext *ctx, const char *path)
                    489: {
                    490:     return remove(rpath(ctx, path));
                    491: }
                    492: 
1.1.1.2 ! root      493: static int local_fsync(FsContext *ctx, int fd, int datasync)
        !           494: {
        !           495:     if (datasync) {
        !           496:         return qemu_fdatasync(fd);
        !           497:     } else {
        !           498:         return fsync(fd);
        !           499:     }
        !           500: }
        !           501: 
        !           502: static int local_statfs(FsContext *s, const char *path, struct statfs *stbuf)
        !           503: {
        !           504:    return statfs(rpath(s, path), stbuf);
        !           505: }
        !           506: 
        !           507: static ssize_t local_lgetxattr(FsContext *ctx, const char *path,
        !           508:                                const char *name, void *value, size_t size)
1.1       root      509: {
1.1.1.2 ! root      510:     return v9fs_get_xattr(ctx, path, name, value, size);
1.1       root      511: }
                    512: 
1.1.1.2 ! root      513: static ssize_t local_llistxattr(FsContext *ctx, const char *path,
        !           514:                                 void *value, size_t size)
        !           515: {
        !           516:     return v9fs_list_xattr(ctx, path, value, size);
        !           517: }
        !           518: 
        !           519: static int local_lsetxattr(FsContext *ctx, const char *path, const char *name,
        !           520:                            void *value, size_t size, int flags)
        !           521: {
        !           522:     return v9fs_set_xattr(ctx, path, name, value, size, flags);
        !           523: }
        !           524: 
        !           525: static int local_lremovexattr(FsContext *ctx,
        !           526:                               const char *path, const char *name)
        !           527: {
        !           528:     return v9fs_remove_xattr(ctx, path, name);
        !           529: }
        !           530: 
        !           531: 
1.1       root      532: FileOperations local_ops = {
                    533:     .lstat = local_lstat,
                    534:     .readlink = local_readlink,
                    535:     .close = local_close,
                    536:     .closedir = local_closedir,
                    537:     .open = local_open,
                    538:     .opendir = local_opendir,
                    539:     .rewinddir = local_rewinddir,
                    540:     .telldir = local_telldir,
                    541:     .readdir = local_readdir,
                    542:     .seekdir = local_seekdir,
1.1.1.2 ! root      543:     .preadv = local_preadv,
        !           544:     .pwritev = local_pwritev,
1.1       root      545:     .chmod = local_chmod,
                    546:     .mknod = local_mknod,
                    547:     .mkdir = local_mkdir,
                    548:     .fstat = local_fstat,
                    549:     .open2 = local_open2,
                    550:     .symlink = local_symlink,
                    551:     .link = local_link,
                    552:     .truncate = local_truncate,
                    553:     .rename = local_rename,
                    554:     .chown = local_chown,
1.1.1.2 ! root      555:     .utimensat = local_utimensat,
1.1       root      556:     .remove = local_remove,
                    557:     .fsync = local_fsync,
1.1.1.2 ! root      558:     .statfs = local_statfs,
        !           559:     .lgetxattr = local_lgetxattr,
        !           560:     .llistxattr = local_llistxattr,
        !           561:     .lsetxattr = local_lsetxattr,
        !           562:     .lremovexattr = local_lremovexattr,
1.1       root      563: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.