Annotation of qemu/hw/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: #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.