On 2019-11-05, Mike Rapoport wrote: > Current implementation of UFFD_FEATURE_EVENT_FORK modifies the file > descriptor table from the read() implementation of uffd, which may have > security implications for unprivileged use of the userfaultfd. > > Limit availability of UFFD_FEATURE_EVENT_FORK only for callers that have > CAP_SYS_PTRACE. > > Signed-off-by: Mike Rapoport > --- > fs/userfaultfd.c | 18 +++++++++++------- > 1 file changed, 11 insertions(+), 7 deletions(-) > > diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c > index f9fd18670e22..d99d166fd892 100644 > --- a/fs/userfaultfd.c > +++ b/fs/userfaultfd.c > @@ -1834,13 +1834,12 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx, > if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api))) > goto out; > 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; > - } > + ret = -EINVAL; > + if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES)) > + goto err_out; > + ret = -EPERM; > + if ((features & UFFD_FEATURE_EVENT_FORK) && !capable(CAP_SYS_PTRACE)) > + goto err_out; > /* report all available features and ioctls to userland */ > uffdio_api.features = UFFD_API_FEATURES; > uffdio_api.ioctls = UFFD_API_IOCTLS; > @@ -1853,6 +1852,11 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx, > ret = 0; > out: > return ret; > +err_out: > + memset(&uffdio_api, 0, sizeof(uffdio_api)); > + if (copy_to_user(buf, &uffdio_api, sizeof(uffdio_api))) Wouldn't it be simpler to do clear_user()? > + ret = -EFAULT; > + goto out; > } > > static long userfaultfd_ioctl(struct file *file, unsigned cmd, -- Aleksa Sarai Senior Software Engineer (Containers) SUSE Linux GmbH