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

unix.superglobalmegacorp.com

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