This will allow userland to probe all features available in the kernel. It will however only enable the requested features in the open userfaultfd context.
Unified · Split
| @@ -1285,6 +1285,7 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx, · 1284 unmodified lines | |||
| 1285 | struct uffdio_api uffdio_api; | 1285 | struct uffdio_api uffdio_api; |
| 1286 | void __user *buf = (void __user *)arg; | 1286 | void __user *buf = (void __user *)arg; |
| 1287 | int ret; | 1287 | int ret; |
| 1288 | __u64 features; | ||
| 1288 | 1289 | ||
| 1289 | ret = -EINVAL; | 1290 | ret = -EINVAL; |
| 1290 | if (ctx->state != UFFD_STATE_WAIT_API) | 1291 | if (ctx->state != UFFD_STATE_WAIT_API) |
| @@ -1292,21 +1293,23 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx, · 1 unmodified line | |||
| 1292 | ret = -EFAULT; | 1293 | ret = -EFAULT; |
| 1293 | if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api))) | 1294 | if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api))) |
| 1294 | goto out; | 1295 | goto out; |
| 1295 | if (uffdio_api.api != UFFD_API || | 1296 | features = uffdio_api.features; |
| 1296 | (uffdio_api.features & ~UFFD_API_FEATURES)) { | 1297 | if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) { |
| 1297 | memset(&uffdio_api, 0, sizeof(uffdio_api)); | 1298 | memset(&uffdio_api, 0, sizeof(uffdio_api)); |
| 1298 | if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) | 1299 | if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) |
| 1299 | goto out; | 1300 | goto out; |
| 1300 | ret = -EINVAL; | 1301 | ret = -EINVAL; |
| 1301 | goto out; | 1302 | goto out; |
| 1302 | } | 1303 | } |
| 1303 | uffdio_api.features &= UFFD_API_FEATURES; | 1304 | /* report all available features and ioctls to userland */ |
| 1305 | uffdio_api.features = UFFD_API_FEATURES; | ||
| 1304 | uffdio_api.ioctls = UFFD_API_IOCTLS; | 1306 | uffdio_api.ioctls = UFFD_API_IOCTLS; |
| 1305 | ret = -EFAULT; | 1307 | ret = -EFAULT; |
| 1306 | if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) | 1308 | if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) |
| 1307 | goto out; | 1309 | goto out; |
| 1308 | ctx->state = UFFD_STATE_RUNNING; | 1310 | ctx->state = UFFD_STATE_RUNNING; |
| 1309 | ctx->features = uffd_ctx_features(uffdio_api.features); | 1311 | /* only enable the requested features for this uffd context */ |
| 1312 | ctx->features = uffd_ctx_features(features); | ||
| 1310 | ret = 0; | 1313 | ret = 0; |
| 1311 | out: | 1314 | out: |
| 1312 | return ret; | 1315 | return ret; |