When path is truncated by PATH_MAX limitation, it causes QEMU to access incorrect file. So use original full path instead of PATH_MAX within 9pfs (need check/process ENOMEM for related memory allocation). The related test: - Environments (for qemu-devel): - Host is under fedora17 desktop with ext4fs: qemu-system-x86_64 -hda test.img -m 1024 \ -net nic,vlan=4,model=virtio,macaddr=00:16:35:AF:94:04 \ -net tap,vlan=4,ifname=tap4,script=no,downscript=no \ -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \ -fsdev local,security_model=passthrough,id=fsdev0,\ path=/upstream/vm/data/share/1234567890abcdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmnopqrstuvwxyz\ ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111111111\ 1111111111111111111111111111111111111111111111111111222222222222\ 2222222222222222222222222222222222222222222222222222222222222222\ 2222222222222222222222222222222222233333333333333333333333333333\ 3333333333333333333333333333333333 - Guest is ubuntu12 server with 9pfs. mount -t 9p -o trans=virtio,version=9p2000.L hostshare /share - Limitations: full path limitation is PATH_MAX (4096B include nul) under Linux. file/dir node name maximized length is 256 (include nul) under ext4. - Special test: Under host, modify the file: "/upstream/vm/data/share/1234567890abcdefg\ hijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890acdefghijklmno\ pqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890/111111111111111111111\ 111111111111111111111111111111111111111111111111111111111122222222222\ 222222222222222222222222222222222222222222222222222222222222222222222\ 222222222222222222222222222222233333333333333333333333333333333333333\ 3333333333333333333333333/4444444444444444444444444444444444444444444\ 444444444444444444444444444444444444444444444444444444444444444444444\ 444444444444444444444444444444444444444444444444444444444444444444444\ 444444444444444444444444444444444444444/55555555555555555555555555555\ 555555555555555555555555555555555555555555555555555555555555555555555\ 555555555555555555555555555555555555555555555555555555555555555555555\ 555555555555555555555555555555555555555555555555555555555555555555555\ 55555555/666666666666666666666666666666666666666666666666666666666666\ 666666666666666666666666666666666666666666666666666666666666666666666\ 666666666666666666666666666666666666666666666666666666666666666666666\ 666666666666666666666/77777777777777777777777777777777777777777777777\ 777777777777777777777777777777777777777777777777777777777777777777777\ 777777777777777777777777777777777777777777777777777777777777777777777\ 77777777777777777777777777777777777777777777777777777777777/888888888\ 888888888888888888888888888888888888888888888888888888888888888888888\ 888888888888888888888888888888888888888888888888888888888888888888888\ 888888888888888888888888888888888888888888888888888888888888888888888\ 888888888/99999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999\ 999999999999999999999999999999999999999999999999999999999999999999999\ 99999999999999999999999999999999999999999/000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000000000000000/aaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbb\ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ccccccccc\ ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\ ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\ ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc\ cccccccccc/dddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\ ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\ ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd\ dddddddddddddddddddddd/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\ eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\ eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\ eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee/fffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\ ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff/gggggggggg\ ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\ ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\ ggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggggg\ ggggggggggggggggggggggg/iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\ iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\ iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii\ iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii/jjjjjjjjjjjjj\ jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj\ jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj/ppppppppppppppppppppp\ ppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppppp\ ppppppppppppppppppppppppppppppppppppppp/test1234567890file.log" (need enter dir firstly, then modify file, or can not open it). Under guest, still allow modify "test1234567890file.log" (will generate "test123456" file with contents). After apply this patch, can not open "test1234567890file.log" under guest (permission denied). - Common test: All are still OK after apply this path. "mkdir -p", "create/open file/dir", "modify file/dir", "rm file/dir". change various mount point paths under host and/or guest. Signed-off-by: Chen Gang <gang.chen.5i5j@gmail.com> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
186 lines
4.5 KiB
C
186 lines
4.5 KiB
C
/*
|
|
* Virtio 9p system.posix* xattr callback
|
|
*
|
|
* Copyright IBM, Corp. 2010
|
|
*
|
|
* Authors:
|
|
* Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2. See
|
|
* the COPYING file in the top-level directory.
|
|
*
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include "qemu/xattr.h"
|
|
#include "hw/virtio/virtio.h"
|
|
#include "virtio-9p.h"
|
|
#include "fsdev/file-op-9p.h"
|
|
#include "virtio-9p-xattr.h"
|
|
|
|
#define MAP_ACL_ACCESS "user.virtfs.system.posix_acl_access"
|
|
#define MAP_ACL_DEFAULT "user.virtfs.system.posix_acl_default"
|
|
#define ACL_ACCESS "system.posix_acl_access"
|
|
#define ACL_DEFAULT "system.posix_acl_default"
|
|
|
|
static ssize_t mp_pacl_getxattr(FsContext *ctx, const char *path,
|
|
const char *name, void *value, size_t size)
|
|
{
|
|
char *buffer;
|
|
ssize_t ret;
|
|
|
|
buffer = rpath(ctx, path);
|
|
ret = lgetxattr(buffer, MAP_ACL_ACCESS, value, size);
|
|
g_free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t mp_pacl_listxattr(FsContext *ctx, const char *path,
|
|
char *name, void *value, size_t osize)
|
|
{
|
|
ssize_t len = sizeof(ACL_ACCESS);
|
|
|
|
if (!value) {
|
|
return len;
|
|
}
|
|
|
|
if (osize < len) {
|
|
errno = ERANGE;
|
|
return -1;
|
|
}
|
|
|
|
/* len includes the trailing NUL */
|
|
memcpy(value, ACL_ACCESS, len);
|
|
return 0;
|
|
}
|
|
|
|
static int mp_pacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
|
void *value, size_t size, int flags)
|
|
{
|
|
char *buffer;
|
|
int ret;
|
|
|
|
buffer = rpath(ctx, path);
|
|
ret = lsetxattr(buffer, MAP_ACL_ACCESS, value, size, flags);
|
|
g_free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
static int mp_pacl_removexattr(FsContext *ctx,
|
|
const char *path, const char *name)
|
|
{
|
|
int ret;
|
|
char *buffer;
|
|
|
|
buffer = rpath(ctx, path);
|
|
ret = lremovexattr(buffer, MAP_ACL_ACCESS);
|
|
if (ret == -1 && errno == ENODATA) {
|
|
/*
|
|
* We don't get ENODATA error when trying to remove a
|
|
* posix acl that is not present. So don't throw the error
|
|
* even in case of mapped security model
|
|
*/
|
|
errno = 0;
|
|
ret = 0;
|
|
}
|
|
g_free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t mp_dacl_getxattr(FsContext *ctx, const char *path,
|
|
const char *name, void *value, size_t size)
|
|
{
|
|
char *buffer;
|
|
ssize_t ret;
|
|
|
|
buffer = rpath(ctx, path);
|
|
ret = lgetxattr(buffer, MAP_ACL_DEFAULT, value, size);
|
|
g_free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
static ssize_t mp_dacl_listxattr(FsContext *ctx, const char *path,
|
|
char *name, void *value, size_t osize)
|
|
{
|
|
ssize_t len = sizeof(ACL_DEFAULT);
|
|
|
|
if (!value) {
|
|
return len;
|
|
}
|
|
|
|
if (osize < len) {
|
|
errno = ERANGE;
|
|
return -1;
|
|
}
|
|
|
|
/* len includes the trailing NUL */
|
|
memcpy(value, ACL_ACCESS, len);
|
|
return 0;
|
|
}
|
|
|
|
static int mp_dacl_setxattr(FsContext *ctx, const char *path, const char *name,
|
|
void *value, size_t size, int flags)
|
|
{
|
|
char *buffer;
|
|
int ret;
|
|
|
|
buffer = rpath(ctx, path);
|
|
ret = lsetxattr(buffer, MAP_ACL_DEFAULT, value, size, flags);
|
|
g_free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
static int mp_dacl_removexattr(FsContext *ctx,
|
|
const char *path, const char *name)
|
|
{
|
|
int ret;
|
|
char *buffer;
|
|
|
|
buffer = rpath(ctx, path);
|
|
ret = lremovexattr(buffer, MAP_ACL_DEFAULT);
|
|
if (ret == -1 && errno == ENODATA) {
|
|
/*
|
|
* We don't get ENODATA error when trying to remove a
|
|
* posix acl that is not present. So don't throw the error
|
|
* even in case of mapped security model
|
|
*/
|
|
errno = 0;
|
|
ret = 0;
|
|
}
|
|
g_free(buffer);
|
|
return ret;
|
|
}
|
|
|
|
|
|
XattrOperations mapped_pacl_xattr = {
|
|
.name = "system.posix_acl_access",
|
|
.getxattr = mp_pacl_getxattr,
|
|
.setxattr = mp_pacl_setxattr,
|
|
.listxattr = mp_pacl_listxattr,
|
|
.removexattr = mp_pacl_removexattr,
|
|
};
|
|
|
|
XattrOperations mapped_dacl_xattr = {
|
|
.name = "system.posix_acl_default",
|
|
.getxattr = mp_dacl_getxattr,
|
|
.setxattr = mp_dacl_setxattr,
|
|
.listxattr = mp_dacl_listxattr,
|
|
.removexattr = mp_dacl_removexattr,
|
|
};
|
|
|
|
XattrOperations passthrough_acl_xattr = {
|
|
.name = "system.posix_acl_",
|
|
.getxattr = pt_getxattr,
|
|
.setxattr = pt_setxattr,
|
|
.listxattr = pt_listxattr,
|
|
.removexattr = pt_removexattr,
|
|
};
|
|
|
|
XattrOperations none_acl_xattr = {
|
|
.name = "system.posix_acl_",
|
|
.getxattr = notsup_getxattr,
|
|
.setxattr = notsup_setxattr,
|
|
.listxattr = notsup_listxattr,
|
|
.removexattr = notsup_removexattr,
|
|
};
|