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 | 1285 | struct uffdio_api uffdio_api; |
| 1286 | 1286 | void __user *buf = (void __user *)arg; |
| 1287 | 1287 | int ret; |
| 1288 | + __u64 features; | |
| 1288 | 1289 | |
| 1289 | 1290 | ret = -EINVAL; |
| 1290 | 1291 | if (ctx->state != UFFD_STATE_WAIT_API) |
| @@ -1292,21 +1293,23 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx, · 1 unmodified line | ||
| 1292 | 1293 | ret = -EFAULT; |
| 1293 | 1294 | if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api))) |
| 1294 | 1295 | goto out; |
| 1295 | − if (uffdio_api.api != UFFD_API || | |
| 1296 | − (uffdio_api.features & ~UFFD_API_FEATURES)) { | |
| 1296 | + features = uffdio_api.features; | |
| 1297 | + if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) { | |
| 1297 | 1298 | memset(&uffdio_api, 0, sizeof(uffdio_api)); |
| 1298 | 1299 | if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) |
| 1299 | 1300 | goto out; |
| 1300 | 1301 | ret = -EINVAL; |
| 1301 | 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 | 1306 | uffdio_api.ioctls = UFFD_API_IOCTLS; |
| 1305 | 1307 | ret = -EFAULT; |
| 1306 | 1308 | if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) |
| 1307 | 1309 | goto out; |
| 1308 | 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 | 1313 | ret = 0; |
| 1311 | 1314 | out: |
| 1312 | 1315 | return ret; |