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

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"
        !            15: #include <arpa/inet.h>
        !            16: #include <pwd.h>
        !            17: #include <grp.h>
        !            18: #include <sys/socket.h>
        !            19: #include <sys/un.h>
        !            20: #include <attr/xattr.h>
        !            21: 
        !            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: 
        !            31: static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
        !            32: {
        !            33:     int err;
        !            34:     err =  lstat(rpath(fs_ctx, path), stbuf);
        !            35:     if (err) {
        !            36:         return err;
        !            37:     }
        !            38:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !            39:         /* Actual credentials are part of extended attrs */
        !            40:         uid_t tmp_uid;
        !            41:         gid_t tmp_gid;
        !            42:         mode_t tmp_mode;
        !            43:         dev_t tmp_dev;
        !            44:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid,
        !            45:                     sizeof(uid_t)) > 0) {
        !            46:             stbuf->st_uid = tmp_uid;
        !            47:         }
        !            48:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid,
        !            49:                     sizeof(gid_t)) > 0) {
        !            50:             stbuf->st_gid = tmp_gid;
        !            51:         }
        !            52:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode,
        !            53:                     sizeof(mode_t)) > 0) {
        !            54:             stbuf->st_mode = tmp_mode;
        !            55:         }
        !            56:         if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
        !            57:                         sizeof(dev_t)) > 0) {
        !            58:                 stbuf->st_rdev = tmp_dev;
        !            59:         }
        !            60:     }
        !            61:     return err;
        !            62: }
        !            63: 
        !            64: static int local_set_xattr(const char *path, FsCred *credp)
        !            65: {
        !            66:     int err;
        !            67:     if (credp->fc_uid != -1) {
        !            68:         err = setxattr(path, "user.virtfs.uid", &credp->fc_uid, sizeof(uid_t),
        !            69:                 0);
        !            70:         if (err) {
        !            71:             return err;
        !            72:         }
        !            73:     }
        !            74:     if (credp->fc_gid != -1) {
        !            75:         err = setxattr(path, "user.virtfs.gid", &credp->fc_gid, sizeof(gid_t),
        !            76:                 0);
        !            77:         if (err) {
        !            78:             return err;
        !            79:         }
        !            80:     }
        !            81:     if (credp->fc_mode != -1) {
        !            82:         err = setxattr(path, "user.virtfs.mode", &credp->fc_mode,
        !            83:                 sizeof(mode_t), 0);
        !            84:         if (err) {
        !            85:             return err;
        !            86:         }
        !            87:     }
        !            88:     if (credp->fc_rdev != -1) {
        !            89:         err = setxattr(path, "user.virtfs.rdev", &credp->fc_rdev,
        !            90:                 sizeof(dev_t), 0);
        !            91:         if (err) {
        !            92:             return err;
        !            93:         }
        !            94:     }
        !            95:     return 0;
        !            96: }
        !            97: 
        !            98: static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
        !            99:         FsCred *credp)
        !           100: {
        !           101:     if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) {
        !           102:         return -1;
        !           103:     }
        !           104:     if (chown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid) < 0) {
        !           105:         return -1;
        !           106:     }
        !           107:     return 0;
        !           108: }
        !           109: 
        !           110: static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
        !           111:         char *buf, size_t bufsz)
        !           112: {
        !           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;
        !           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: 
        !           171: static ssize_t local_readv(FsContext *ctx, int fd, const struct iovec *iov,
        !           172:                             int iovcnt)
        !           173: {
        !           174:     return readv(fd, iov, iovcnt);
        !           175: }
        !           176: 
        !           177: static off_t local_lseek(FsContext *ctx, int fd, off_t offset, int whence)
        !           178: {
        !           179:     return lseek(fd, offset, whence);
        !           180: }
        !           181: 
        !           182: static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
        !           183:                             int iovcnt)
        !           184: {
        !           185:     return writev(fd, iov, iovcnt);
        !           186: }
        !           187: 
        !           188: static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
        !           189: {
        !           190:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !           191:         return local_set_xattr(rpath(fs_ctx, path), credp);
        !           192:     } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
        !           193:         return chmod(rpath(fs_ctx, path), credp->fc_mode);
        !           194:     }
        !           195:     return -1;
        !           196: }
        !           197: 
        !           198: static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
        !           199: {
        !           200:     int err = -1;
        !           201:     int serrno = 0;
        !           202: 
        !           203:     /* Determine the security model */
        !           204:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !           205:         err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0);
        !           206:         if (err == -1) {
        !           207:             return err;
        !           208:         }
        !           209:         local_set_xattr(rpath(fs_ctx, path), credp);
        !           210:         if (err == -1) {
        !           211:             serrno = errno;
        !           212:             goto err_end;
        !           213:         }
        !           214:     } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
        !           215:         err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev);
        !           216:         if (err == -1) {
        !           217:             return err;
        !           218:         }
        !           219:         err = local_post_create_passthrough(fs_ctx, path, credp);
        !           220:         if (err == -1) {
        !           221:             serrno = errno;
        !           222:             goto err_end;
        !           223:         }
        !           224:     }
        !           225:     return err;
        !           226: 
        !           227: err_end:
        !           228:     remove(rpath(fs_ctx, path));
        !           229:     errno = serrno;
        !           230:     return err;
        !           231: }
        !           232: 
        !           233: static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
        !           234: {
        !           235:     int err = -1;
        !           236:     int serrno = 0;
        !           237: 
        !           238:     /* Determine the security model */
        !           239:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !           240:         err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS);
        !           241:         if (err == -1) {
        !           242:             return err;
        !           243:         }
        !           244:         credp->fc_mode = credp->fc_mode|S_IFDIR;
        !           245:         err = local_set_xattr(rpath(fs_ctx, path), credp);
        !           246:         if (err == -1) {
        !           247:             serrno = errno;
        !           248:             goto err_end;
        !           249:         }
        !           250:     } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
        !           251:         err = mkdir(rpath(fs_ctx, path), credp->fc_mode);
        !           252:         if (err == -1) {
        !           253:             return err;
        !           254:         }
        !           255:         err = local_post_create_passthrough(fs_ctx, path, credp);
        !           256:         if (err == -1) {
        !           257:             serrno = errno;
        !           258:             goto err_end;
        !           259:         }
        !           260:     }
        !           261:     return err;
        !           262: 
        !           263: err_end:
        !           264:     remove(rpath(fs_ctx, path));
        !           265:     errno = serrno;
        !           266:     return err;
        !           267: }
        !           268: 
        !           269: static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
        !           270: {
        !           271:     int err;
        !           272:     err = fstat(fd, stbuf);
        !           273:     if (err) {
        !           274:         return err;
        !           275:     }
        !           276:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !           277:         /* Actual credentials are part of extended attrs */
        !           278:         uid_t tmp_uid;
        !           279:         gid_t tmp_gid;
        !           280:         mode_t tmp_mode;
        !           281:         dev_t tmp_dev;
        !           282: 
        !           283:         if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
        !           284:             stbuf->st_uid = tmp_uid;
        !           285:         }
        !           286:         if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
        !           287:             stbuf->st_gid = tmp_gid;
        !           288:         }
        !           289:         if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
        !           290:             stbuf->st_mode = tmp_mode;
        !           291:         }
        !           292:         if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
        !           293:                 stbuf->st_rdev = tmp_dev;
        !           294:         }
        !           295:     }
        !           296:     return err;
        !           297: }
        !           298: 
        !           299: static int local_open2(FsContext *fs_ctx, const char *path, int flags,
        !           300:         FsCred *credp)
        !           301: {
        !           302:     int fd = -1;
        !           303:     int err = -1;
        !           304:     int serrno = 0;
        !           305: 
        !           306:     /* Determine the security model */
        !           307:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !           308:         fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS);
        !           309:         if (fd == -1) {
        !           310:             return fd;
        !           311:         }
        !           312:         credp->fc_mode = credp->fc_mode|S_IFREG;
        !           313:         /* Set cleint credentials in xattr */
        !           314:         err = local_set_xattr(rpath(fs_ctx, path), credp);
        !           315:         if (err == -1) {
        !           316:             serrno = errno;
        !           317:             goto err_end;
        !           318:         }
        !           319:     } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
        !           320:         fd = open(rpath(fs_ctx, path), flags, credp->fc_mode);
        !           321:         if (fd == -1) {
        !           322:             return fd;
        !           323:         }
        !           324:         err = local_post_create_passthrough(fs_ctx, path, credp);
        !           325:         if (err == -1) {
        !           326:             serrno = errno;
        !           327:             goto err_end;
        !           328:         }
        !           329:     }
        !           330:     return fd;
        !           331: 
        !           332: err_end:
        !           333:     close(fd);
        !           334:     remove(rpath(fs_ctx, path));
        !           335:     errno = serrno;
        !           336:     return err;
        !           337: }
        !           338: 
        !           339: 
        !           340: static int local_symlink(FsContext *fs_ctx, const char *oldpath,
        !           341:         const char *newpath, FsCred *credp)
        !           342: {
        !           343:     int err = -1;
        !           344:     int serrno = 0;
        !           345: 
        !           346:     /* Determine the security model */
        !           347:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !           348:         int fd;
        !           349:         ssize_t oldpath_size, write_size;
        !           350:         fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
        !           351:                 SM_LOCAL_MODE_BITS);
        !           352:         if (fd == -1) {
        !           353:             return fd;
        !           354:         }
        !           355:         /* Write the oldpath (target) to the file. */
        !           356:         oldpath_size = strlen(oldpath) + 1;
        !           357:         do {
        !           358:             write_size = write(fd, (void *)oldpath, oldpath_size);
        !           359:         } while (write_size == -1 && errno == EINTR);
        !           360: 
        !           361:         if (write_size != oldpath_size) {
        !           362:             serrno = errno;
        !           363:             close(fd);
        !           364:             err = -1;
        !           365:             goto err_end;
        !           366:         }
        !           367:         close(fd);
        !           368:         /* Set cleint credentials in symlink's xattr */
        !           369:         credp->fc_mode = credp->fc_mode|S_IFLNK;
        !           370:         err = local_set_xattr(rpath(fs_ctx, newpath), credp);
        !           371:         if (err == -1) {
        !           372:             serrno = errno;
        !           373:             goto err_end;
        !           374:         }
        !           375:     } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
        !           376:         err = symlink(oldpath, rpath(fs_ctx, newpath));
        !           377:         if (err) {
        !           378:             return err;
        !           379:         }
        !           380:         err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
        !           381:         if (err == -1) {
        !           382:             serrno = errno;
        !           383:             goto err_end;
        !           384:         }
        !           385:     }
        !           386:     return err;
        !           387: 
        !           388: err_end:
        !           389:     remove(rpath(fs_ctx, newpath));
        !           390:     errno = serrno;
        !           391:     return err;
        !           392: }
        !           393: 
        !           394: static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
        !           395: {
        !           396:     char *tmp = qemu_strdup(rpath(ctx, oldpath));
        !           397:     int err, serrno = 0;
        !           398: 
        !           399:     if (tmp == NULL) {
        !           400:         return -ENOMEM;
        !           401:     }
        !           402: 
        !           403:     err = link(tmp, rpath(ctx, newpath));
        !           404:     if (err == -1) {
        !           405:         serrno = errno;
        !           406:     }
        !           407: 
        !           408:     qemu_free(tmp);
        !           409: 
        !           410:     if (err == -1) {
        !           411:         errno = serrno;
        !           412:     }
        !           413: 
        !           414:     return err;
        !           415: }
        !           416: 
        !           417: static int local_truncate(FsContext *ctx, const char *path, off_t size)
        !           418: {
        !           419:     return truncate(rpath(ctx, path), size);
        !           420: }
        !           421: 
        !           422: static int local_rename(FsContext *ctx, const char *oldpath,
        !           423:                         const char *newpath)
        !           424: {
        !           425:     char *tmp;
        !           426:     int err;
        !           427: 
        !           428:     tmp = qemu_strdup(rpath(ctx, oldpath));
        !           429:     if (tmp == NULL) {
        !           430:         return -1;
        !           431:     }
        !           432: 
        !           433:     err = rename(tmp, rpath(ctx, newpath));
        !           434:     if (err == -1) {
        !           435:         int serrno = errno;
        !           436:         qemu_free(tmp);
        !           437:         errno = serrno;
        !           438:     } else {
        !           439:         qemu_free(tmp);
        !           440:     }
        !           441: 
        !           442:     return err;
        !           443: 
        !           444: }
        !           445: 
        !           446: static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
        !           447: {
        !           448:     if (fs_ctx->fs_sm == SM_MAPPED) {
        !           449:         return local_set_xattr(rpath(fs_ctx, path), credp);
        !           450:     } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
        !           451:         return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
        !           452:     }
        !           453:     return -1;
        !           454: }
        !           455: 
        !           456: static int local_utime(FsContext *ctx, const char *path,
        !           457:                         const struct utimbuf *buf)
        !           458: {
        !           459:     return utime(rpath(ctx, path), buf);
        !           460: }
        !           461: 
        !           462: static int local_remove(FsContext *ctx, const char *path)
        !           463: {
        !           464:     return remove(rpath(ctx, path));
        !           465: }
        !           466: 
        !           467: static int local_fsync(FsContext *ctx, int fd)
        !           468: {
        !           469:     return fsync(fd);
        !           470: }
        !           471: 
        !           472: FileOperations local_ops = {
        !           473:     .lstat = local_lstat,
        !           474:     .readlink = local_readlink,
        !           475:     .close = local_close,
        !           476:     .closedir = local_closedir,
        !           477:     .open = local_open,
        !           478:     .opendir = local_opendir,
        !           479:     .rewinddir = local_rewinddir,
        !           480:     .telldir = local_telldir,
        !           481:     .readdir = local_readdir,
        !           482:     .seekdir = local_seekdir,
        !           483:     .readv = local_readv,
        !           484:     .lseek = local_lseek,
        !           485:     .writev = local_writev,
        !           486:     .chmod = local_chmod,
        !           487:     .mknod = local_mknod,
        !           488:     .mkdir = local_mkdir,
        !           489:     .fstat = local_fstat,
        !           490:     .open2 = local_open2,
        !           491:     .symlink = local_symlink,
        !           492:     .link = local_link,
        !           493:     .truncate = local_truncate,
        !           494:     .rename = local_rename,
        !           495:     .chown = local_chown,
        !           496:     .utime = local_utime,
        !           497:     .remove = local_remove,
        !           498:     .fsync = local_fsync,
        !           499: };

unix.superglobalmegacorp.com

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