summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/userfaultfd.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index b5074a344635..87d31921b66c 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -1285,6 +1285,7 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
struct uffdio_api uffdio_api;
void __user *buf = (void __user *)arg;
int ret;
+ __u64 features;
ret = -EINVAL;
if (ctx->state != UFFD_STATE_WAIT_API)
@@ -1292,21 +1293,23 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
ret = -EFAULT;
if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api)))
goto out;
- if (uffdio_api.api != UFFD_API ||
- (uffdio_api.features & ~UFFD_API_FEATURES)) {
+ features = uffdio_api.features;
+ if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) {
memset(&uffdio_api, 0, sizeof(uffdio_api));
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
goto out;
ret = -EINVAL;
goto out;
}
- uffdio_api.features &= UFFD_API_FEATURES;
+ /* report all available features and ioctls to userland */
+ uffdio_api.features = UFFD_API_FEATURES;
uffdio_api.ioctls = UFFD_API_IOCTLS;
ret = -EFAULT;
if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api)))
goto out;
ctx->state = UFFD_STATE_RUNNING;
- ctx->features = uffd_ctx_features(uffdio_api.features);
+ /* only enable the requested features for this uffd context */
+ ctx->features = uffd_ctx_features(features);
ret = 0;
out:
return ret;