aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-06-07 16:22:57 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-06-07 16:22:57 +0100
commita674da0ab7eae704c3f91749114ec6ca00c663d7 (patch)
tree23f8503e8b1977f8dd1d41cfa74cc840ade5d691
parent8e36d27c5a7b99a7adb40cfda2f92b1d97216e84 (diff)
parentaca6897fba149a2a650dcdf5a5e1ae828371f4aa (diff)
Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging
Mostly bug fixes and code sanitization motivated by the upcoming support for Darwin hosts. Thanks to Keno Fischer. # gpg: Signature made Thu 07 Jun 2018 11:30:56 BST # gpg: using RSA key 71D4D5E5822F73D6 # gpg: Good signature from "Greg Kurz <groug@kaod.org>" # gpg: aka "Gregory Kurz <gregory.kurz@free.fr>" # gpg: aka "[jpeg image of size 3330]" # Primary key fingerprint: B482 8BAF 9431 40CE F2A3 4910 71D4 D5E5 822F 73D6 * remotes/gkurz/tags/for-upstream: 9p: xattr: Properly translate xattrcreate flags 9p: Properly check/translate flags in unlinkat 9p: local: Avoid warning if FS_IOC_GETVERSION is not defined 9p: xattr: Fix crashes due to free of uninitialized value 9p: Move a couple xattr functions to 9p-util 9p: local: Properly set errp in fstatfs error path 9p: proxy: Fix size passed to `connect` Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/9pfs/9p-handle.c8
-rw-r--r--hw/9pfs/9p-local.c40
-rw-r--r--hw/9pfs/9p-proxy.c5
-rw-r--r--hw/9pfs/9p-util.c33
-rw-r--r--hw/9pfs/9p-util.h4
-rw-r--r--hw/9pfs/9p-xattr.c33
-rw-r--r--hw/9pfs/9p.c34
-rw-r--r--hw/9pfs/9p.h4
8 files changed, 96 insertions, 65 deletions
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 4dc0d2bed1..f3641dbe4a 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -559,19 +559,13 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
{
int dirfd, ret;
HandleData *data = (HandleData *) ctx->private;
- int rflags;
dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
if (dirfd < 0) {
return dirfd;
}
- rflags = 0;
- if (flags & P9_DOTL_AT_REMOVEDIR) {
- rflags |= AT_REMOVEDIR;
- }
-
- ret = unlinkat(dirfd, name, rflags);
+ ret = unlinkat(dirfd, name, flags);
close(dirfd);
return ret;
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index b37b1db453..5721eff1e1 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -1373,10 +1373,10 @@ static int local_unlinkat(FsContext *ctx, V9fsPath *dir,
return ret;
}
+#ifdef FS_IOC_GETVERSION
static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
mode_t st_mode, uint64_t *st_gen)
{
-#ifdef FS_IOC_GETVERSION
int err;
V9fsFidOpenState fid_open;
@@ -1395,30 +1395,21 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
local_close(ctx, &fid_open);
return err;
-#else
- errno = ENOTTY;
- return -1;
-#endif
}
+#endif
-static int local_init(FsContext *ctx, Error **errp)
+static int local_ioc_getversion_init(FsContext *ctx, LocalData *data, Error **errp)
{
+#ifdef FS_IOC_GETVERSION
struct statfs stbuf;
- LocalData *data = g_malloc(sizeof(*data));
- data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY);
- if (data->mountfd == -1) {
- error_setg_errno(errp, errno, "failed to open '%s'", ctx->fs_root);
- goto err;
- }
-
-#ifdef FS_IOC_GETVERSION
/*
* use ioc_getversion only if the ioctl is definied
*/
if (fstatfs(data->mountfd, &stbuf) < 0) {
- close_preserve_errno(data->mountfd);
- goto err;
+ error_setg_errno(errp, errno,
+ "failed to stat file system at '%s'", ctx->fs_root);
+ return -1;
}
switch (stbuf.f_type) {
case EXT2_SUPER_MAGIC:
@@ -1429,6 +1420,23 @@ static int local_init(FsContext *ctx, Error **errp)
break;
}
#endif
+ return 0;
+}
+
+static int local_init(FsContext *ctx, Error **errp)
+{
+ LocalData *data = g_malloc(sizeof(*data));
+
+ data->mountfd = open(ctx->fs_root, O_DIRECTORY | O_RDONLY);
+ if (data->mountfd == -1) {
+ error_setg_errno(errp, errno, "failed to open '%s'", ctx->fs_root);
+ goto err;
+ }
+
+ if (local_ioc_getversion_init(ctx, data, errp) < 0) {
+ close(data->mountfd);
+ goto err;
+ }
if (ctx->export_flags & V9FS_SM_PASSTHROUGH) {
ctx->xops = passthrough_xattr_ops;
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index e2e03292de..47a94e088d 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -1088,7 +1088,7 @@ static int proxy_ioc_getversion(FsContext *fs_ctx, V9fsPath *path,
static int connect_namedsocket(const char *path, Error **errp)
{
- int sockfd, size;
+ int sockfd;
struct sockaddr_un helper;
if (strlen(path) >= sizeof(helper.sun_path)) {
@@ -1102,8 +1102,7 @@ static int connect_namedsocket(const char *path, Error **errp)
}
strcpy(helper.sun_path, path);
helper.sun_family = AF_UNIX;
- size = strlen(helper.sun_path) + sizeof(helper.sun_family);
- if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) {
+ if (connect(sockfd, (struct sockaddr *)&helper, sizeof(helper)) < 0) {
error_setg_errno(errp, errno, "failed to connect to '%s'", path);
close(sockfd);
return -1;
diff --git a/hw/9pfs/9p-util.c b/hw/9pfs/9p-util.c
index f709c27a1f..614b7fc34d 100644
--- a/hw/9pfs/9p-util.c
+++ b/hw/9pfs/9p-util.c
@@ -24,3 +24,36 @@ ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name,
g_free(proc_path);
return ret;
}
+
+ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
+ char *list, size_t size)
+{
+ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
+ int ret;
+
+ ret = llistxattr(proc_path, list, size);
+ g_free(proc_path);
+ return ret;
+}
+
+ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
+ const char *name)
+{
+ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
+ int ret;
+
+ ret = lremovexattr(proc_path, name);
+ g_free(proc_path);
+ return ret;
+}
+
+int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
+ void *value, size_t size, int flags)
+{
+ char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
+ int ret;
+
+ ret = lsetxattr(proc_path, name, value, size, flags);
+ g_free(proc_path);
+ return ret;
+}
diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h
index dc0d2e29aa..79ed6b233e 100644
--- a/hw/9pfs/9p-util.h
+++ b/hw/9pfs/9p-util.h
@@ -60,5 +60,9 @@ ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name,
void *value, size_t size);
int fsetxattrat_nofollow(int dirfd, const char *path, const char *name,
void *value, size_t size, int flags);
+ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
+ char *list, size_t size);
+ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
+ const char *name);
#endif
diff --git a/hw/9pfs/9p-xattr.c b/hw/9pfs/9p-xattr.c
index d05c1a1c1d..c696d8f846 100644
--- a/hw/9pfs/9p-xattr.c
+++ b/hw/9pfs/9p-xattr.c
@@ -60,17 +60,6 @@ ssize_t pt_listxattr(FsContext *ctx, const char *path,
return name_size;
}
-static ssize_t flistxattrat_nofollow(int dirfd, const char *filename,
- char *list, size_t size)
-{
- char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
- int ret;
-
- ret = llistxattr(proc_path, list, size);
- g_free(proc_path);
- return ret;
-}
-
/*
* Get the list and pass to each layer to find out whether
* to send the data or not
@@ -196,17 +185,6 @@ ssize_t pt_getxattr(FsContext *ctx, const char *path, const char *name,
return local_getxattr_nofollow(ctx, path, name, value, size);
}
-int fsetxattrat_nofollow(int dirfd, const char *filename, const char *name,
- void *value, size_t size, int flags)
-{
- char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
- int ret;
-
- ret = lsetxattr(proc_path, name, value, size, flags);
- g_free(proc_path);
- return ret;
-}
-
ssize_t local_setxattr_nofollow(FsContext *ctx, const char *path,
const char *name, void *value, size_t size,
int flags)
@@ -235,17 +213,6 @@ int pt_setxattr(FsContext *ctx, const char *path, const char *name, void *value,
return local_setxattr_nofollow(ctx, path, name, value, size, flags);
}
-static ssize_t fremovexattrat_nofollow(int dirfd, const char *filename,
- const char *name)
-{
- char *proc_path = g_strdup_printf("/proc/self/fd/%d/%s", dirfd, filename);
- int ret;
-
- ret = lremovexattr(proc_path, name);
- g_free(proc_path);
- return ret;
-}
-
ssize_t local_removexattr_nofollow(FsContext *ctx, const char *path,
const char *name)
{
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index d74302deeb..eef289e394 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -2522,7 +2522,7 @@ static void coroutine_fn v9fs_unlinkat(void *opaque)
{
int err = 0;
V9fsString name;
- int32_t dfid, flags;
+ int32_t dfid, flags, rflags = 0;
size_t offset = 7;
V9fsPath path;
V9fsFidState *dfidp;
@@ -2549,6 +2549,15 @@ static void coroutine_fn v9fs_unlinkat(void *opaque)
goto out_nofid;
}
+ if (flags & ~P9_DOTL_AT_REMOVEDIR) {
+ err = -EINVAL;
+ goto out_nofid;
+ }
+
+ if (flags & P9_DOTL_AT_REMOVEDIR) {
+ rflags |= AT_REMOVEDIR;
+ }
+
dfidp = get_fid(pdu, dfid);
if (dfidp == NULL) {
err = -EINVAL;
@@ -2567,7 +2576,7 @@ static void coroutine_fn v9fs_unlinkat(void *opaque)
if (err < 0) {
goto out_err;
}
- err = v9fs_co_unlinkat(pdu, &dfidp->path, &name, flags);
+ err = v9fs_co_unlinkat(pdu, &dfidp->path, &name, rflags);
if (!err) {
err = offset;
}
@@ -3256,8 +3265,8 @@ static void coroutine_fn v9fs_xattrwalk(void *opaque)
xattr_fidp->fs.xattr.len = size;
xattr_fidp->fid_type = P9_FID_XATTR;
xattr_fidp->fs.xattr.xattrwalk_fid = true;
+ xattr_fidp->fs.xattr.value = g_malloc0(size);
if (size) {
- xattr_fidp->fs.xattr.value = g_malloc0(size);
err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
xattr_fidp->fs.xattr.value,
xattr_fidp->fs.xattr.len);
@@ -3289,8 +3298,8 @@ static void coroutine_fn v9fs_xattrwalk(void *opaque)
xattr_fidp->fs.xattr.len = size;
xattr_fidp->fid_type = P9_FID_XATTR;
xattr_fidp->fs.xattr.xattrwalk_fid = true;
+ xattr_fidp->fs.xattr.value = g_malloc0(size);
if (size) {
- xattr_fidp->fs.xattr.value = g_malloc0(size);
err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
&name, xattr_fidp->fs.xattr.value,
xattr_fidp->fs.xattr.len);
@@ -3318,7 +3327,7 @@ out_nofid:
static void coroutine_fn v9fs_xattrcreate(void *opaque)
{
- int flags;
+ int flags, rflags = 0;
int32_t fid;
uint64_t size;
ssize_t err = 0;
@@ -3335,6 +3344,19 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque)
}
trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
+ if (flags & ~(P9_XATTR_CREATE | P9_XATTR_REPLACE)) {
+ err = -EINVAL;
+ goto out_nofid;
+ }
+
+ if (flags & P9_XATTR_CREATE) {
+ rflags |= XATTR_CREATE;
+ }
+
+ if (flags & P9_XATTR_REPLACE) {
+ rflags |= XATTR_REPLACE;
+ }
+
if (size > XATTR_SIZE_MAX) {
err = -E2BIG;
goto out_nofid;
@@ -3356,7 +3378,7 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque)
xattr_fidp->fs.xattr.copied_len = 0;
xattr_fidp->fs.xattr.xattrwalk_fid = false;
xattr_fidp->fs.xattr.len = size;
- xattr_fidp->fs.xattr.flags = flags;
+ xattr_fidp->fs.xattr.flags = rflags;
v9fs_string_init(&xattr_fidp->fs.xattr.name);
v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name);
xattr_fidp->fs.xattr.value = g_malloc0(size);
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index bad8ee719c..8883761b2c 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -169,6 +169,10 @@ typedef struct V9fsConf
char *fsdev_id;
} V9fsConf;
+/* 9p2000.L xattr flags (matches Linux values) */
+#define P9_XATTR_CREATE 1
+#define P9_XATTR_REPLACE 2
+
typedef struct V9fsXattr
{
uint64_t copied_len;