1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:37:35 +00:00

Kernel: Don't dereference untrusted userspace pointer in sys$uname()

Instead of writing to the userspace utsname struct one field at a time,
build up a utsname on the kernel stack and copy it out to userspace
once it's finished. This is both simpler and gets validity checking
built-in for free.

Found by KUBSAN! :^)

Fixes #5499.
This commit is contained in:
Andreas Kling 2021-02-24 14:33:50 +01:00
parent 99cd0d3ffb
commit a48d54dfc5

View file

@ -39,18 +39,14 @@ int Process::sys$uname(Userspace<utsname*> buf)
if (g_hostname->length() + 1 > sizeof(utsname::nodename)) if (g_hostname->length() + 1 > sizeof(utsname::nodename))
return -ENAMETOOLONG; return -ENAMETOOLONG;
// We have already validated the entire utsname struct at this utsname buf {};
// point, there is no need to re-validate every write to the struct. memcpy(buf.sysname, "SerenityOS", 11);
utsname* user_buf = buf.unsafe_userspace_ptr(); memcpy(buf.release, "1.0-dev", 8);
if (!copy_to_user(user_buf->sysname, "SerenityOS", 11)) memcpy(buf.version, "FIXME", 6);
return -EFAULT; memcpy(buf.machine, "i686", 5);
if (!copy_to_user(user_buf->release, "1.0-dev", 8)) memcpy(buf.nodename, g_hostname->characters(), g_hostname->length() + 1);
return -EFAULT;
if (!copy_to_user(user_buf->version, "FIXME", 6)) if (!copy_to_user(user_buf, &buf))
return -EFAULT;
if (!copy_to_user(user_buf->machine, "i686", 5))
return -EFAULT;
if (!copy_to_user(user_buf->nodename, g_hostname->characters(), g_hostname->length() + 1))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }