cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

9p-xattr.c (7276B)


      1/*
      2 * 9p  xattr callback
      3 *
      4 * Copyright IBM, Corp. 2010
      5 *
      6 * Authors:
      7 * Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
      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/*
     15 * Not so fast! You might want to read the 9p developer docs first:
     16 * https://wiki.qemu.org/Documentation/9p
     17 */
     18
     19#include "qemu/osdep.h"
     20#include "9p.h"
     21#include "fsdev/file-op-9p.h"
     22#include "9p-xattr.h"
     23#include "9p-util.h"
     24#include "9p-local.h"
     25
     26
     27static XattrOperations *get_xattr_operations(XattrOperations **h,
     28                                             const char *name)
     29{
     30    XattrOperations *xops;
     31    for (xops = *(h)++; xops != NULL; xops = *(h)++) {
     32        if (!strncmp(name, xops->name, strlen(xops->name))) {
     33            return xops;
     34        }
     35    }
     36    return NULL;
     37}
     38
     39ssize_t v9fs_get_xattr(FsContext *ctx, const char *path,
     40                       const char *name, void *value, size_t size)
     41{
     42    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
     43    if (xops) {
     44        return xops->getxattr(ctx, path, name, value, size);
     45    }
     46    errno = EOPNOTSUPP;
     47    return -1;
     48}
     49
     50ssize_t pt_listxattr(FsContext *ctx, const char *path,
     51                     char *name, void *value, size_t size)
     52{
     53    int name_size = strlen(name) + 1;
     54    if (!value) {
     55        return name_size;
     56    }
     57
     58    if (size < name_size) {
     59        errno = ERANGE;
     60        return -1;
     61    }
     62
     63    /* no need for strncpy: name_size is strlen(name)+1 */
     64    memcpy(value, name, name_size);
     65    return name_size;
     66}
     67
     68/*
     69 * Get the list and pass to each layer to find out whether
     70 * to send the data or not
     71 */
     72ssize_t v9fs_list_xattr(FsContext *ctx, const char *path,
     73                        void *value, size_t vsize)
     74{
     75    ssize_t size = 0;
     76    void *ovalue = value;
     77    XattrOperations *xops;
     78    char *orig_value, *orig_value_start;
     79    ssize_t xattr_len, parsed_len = 0, attr_len;
     80    char *dirpath, *name;
     81    int dirfd;
     82
     83    /* Get the actual len */
     84    dirpath = g_path_get_dirname(path);
     85    dirfd = local_opendir_nofollow(ctx, dirpath);
     86    g_free(dirpath);
     87    if (dirfd == -1) {
     88        return -1;
     89    }
     90
     91    name = g_path_get_basename(path);
     92    xattr_len = flistxattrat_nofollow(dirfd, name, value, 0);
     93    if (xattr_len <= 0) {
     94        g_free(name);
     95        close_preserve_errno(dirfd);
     96        return xattr_len;
     97    }
     98
     99    /* Now fetch the xattr and find the actual size */
    100    orig_value = g_malloc(xattr_len);
    101    xattr_len = flistxattrat_nofollow(dirfd, name, orig_value, xattr_len);
    102    g_free(name);
    103    close_preserve_errno(dirfd);
    104    if (xattr_len < 0) {
    105        g_free(orig_value);
    106        return -1;
    107    }
    108
    109    /* store the orig pointer */
    110    orig_value_start = orig_value;
    111    while (xattr_len > parsed_len) {
    112        xops = get_xattr_operations(ctx->xops, orig_value);
    113        if (!xops) {
    114            goto next_entry;
    115        }
    116
    117        if (!value) {
    118            size += xops->listxattr(ctx, path, orig_value, value, vsize);
    119        } else {
    120            size = xops->listxattr(ctx, path, orig_value, value, vsize);
    121            if (size < 0) {
    122                goto err_out;
    123            }
    124            value += size;
    125            vsize -= size;
    126        }
    127next_entry:
    128        /* Got the next entry */
    129        attr_len = strlen(orig_value) + 1;
    130        parsed_len += attr_len;
    131        orig_value += attr_len;
    132    }
    133    if (value) {
    134        size = value - ovalue;
    135    }
    136
    137err_out:
    138    g_free(orig_value_start);
    139    return size;
    140}
    141
    142int v9fs_set_xattr(FsContext *ctx, const char *path, const char *name,
    143                   void *value, size_t size, int flags)
    144{
    145    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
    146    if (xops) {
    147        return xops->setxattr(ctx, path, name, value, size, flags);
    148    }
    149    errno = EOPNOTSUPP;
    150    return -1;
    151
    152}
    153
    154int v9fs_remove_xattr(FsContext *ctx,
    155                      const char *path, const char *name)
    156{
    157    XattrOperations *xops = get_xattr_operations(ctx->xops, name);
    158    if (xops) {
    159        return xops->removexattr(ctx, path, name);
    160    }
    161    errno = EOPNOTSUPP;
    162    return -1;
    163
    164}
    165
    166ssize_t local_getxattr_nofollow(FsContext *ctx, const char *path,
    167                                const char *name, void *value, size_t size)
    168{
    169    char *dirpath = g_path_get_dirname(path);
    170    char *filename = g_path_get_basename(path);
    171    int dirfd;
    172    ssize_t ret = -1;
    173
    174    dirfd = local_opendir_nofollow(ctx, dirpath);
    175    if (dirfd == -1) {
    176        goto out;
    177    }
    178
    179    ret = fgetxattrat_nofollow(dirfd, filename, name, value, size);
    180    close_preserve_errno(dirfd);
    181out:
    182    g_free(dirpath);
    183    g_free(filename);
    184    return ret;
    185}
    186
    187ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
    188                    void *value, size_t size)
    189{
    190    return local_getxattr_nofollow(ctx, path, name, value, size);
    191}
    192
    193ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path,
    194                                const char *name, void *value, size_t size,
    195                                int flags)
    196{
    197    char *dirpath = g_path_get_dirname(path);
    198    char *filename = g_path_get_basename(path);
    199    int dirfd;
    200    ssize_t ret = -1;
    201
    202    dirfd = local_opendir_nofollow(ctx, dirpath);
    203    if (dirfd == -1) {
    204        goto out;
    205    }
    206
    207    ret = fsetxattrat_nofollow(dirfd, filename, name, value, size, flags);
    208    close_preserve_errno(dirfd);
    209out:
    210    g_free(dirpath);
    211    g_free(filename);
    212    return ret;
    213}
    214
    215int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
    216                size_t size, int flags)
    217{
    218    return local_setxattr_nofollow(ctx, path, name, value, size, flags);
    219}
    220
    221ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path,
    222                                   const char *name)
    223{
    224    char *dirpath = g_path_get_dirname(path);
    225    char *filename = g_path_get_basename(path);
    226    int dirfd;
    227    ssize_t ret = -1;
    228
    229    dirfd = local_opendir_nofollow(ctx, dirpath);
    230    if (dirfd == -1) {
    231        goto out;
    232    }
    233
    234    ret = fremovexattrat_nofollow(dirfd, filename, name);
    235    close_preserve_errno(dirfd);
    236out:
    237    g_free(dirpath);
    238    g_free(filename);
    239    return ret;
    240}
    241
    242int pt_removexattr(FsContext *ctx, const char *path, const char *name)
    243{
    244    return local_removexattr_nofollow(ctx, path, name);
    245}
    246
    247ssize_t notsup_getxattr(FsContext *ctx, const char *path, const char *name,
    248                        void *value, size_t size)
    249{
    250    errno = ENOTSUP;
    251    return -1;
    252}
    253
    254int notsup_setxattr(FsContext *ctx, const char *path, const char *name,
    255                    void *value, size_t size, int flags)
    256{
    257    errno = ENOTSUP;
    258    return -1;
    259}
    260
    261ssize_t notsup_listxattr(FsContext *ctx, const char *path, char *name,
    262                         void *value, size_t size)
    263{
    264    return 0;
    265}
    266
    267int notsup_removexattr(FsContext *ctx, const char *path, const char *name)
    268{
    269    errno = ENOTSUP;
    270    return -1;
    271}
    272
    273XattrOperations *mapped_xattr_ops[] = {
    274    &mapped_user_xattr,
    275    &mapped_pacl_xattr,
    276    &mapped_dacl_xattr,
    277    NULL,
    278};
    279
    280XattrOperations *passthrough_xattr_ops[] = {
    281    &passthrough_user_xattr,
    282    &passthrough_acl_xattr,
    283    NULL,
    284};
    285
    286/* for .user none model should be same as passthrough */
    287XattrOperations *none_xattr_ops[] = {
    288    &passthrough_user_xattr,
    289    &none_acl_xattr,
    290    NULL,
    291};