kernel: vfs: common_fcntl() now uses memcpy() for kernel calls.

instead of user_memcpy().

* fix #14204: the NTFS filesystem kernel addon uses the fcntl system call to
lock the underlying device. The user_memcpy replacement in the x86 compat
branch adds range checks for the user pointer, which exposes such problems.
This commit is contained in:
Jérôme Duval
2018-06-30 15:46:52 +02:00
parent 65df4b51f5
commit 4f5ed463b5
+16 -5
View File
@@ -6116,10 +6116,11 @@ common_fcntl(int fd, int op, size_t argument, bool kernel)
if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) { if (op == F_SETLK || op == F_SETLKW || op == F_GETLK) {
if (descriptor->type != FDTYPE_FILE) if (descriptor->type != FDTYPE_FILE)
status = B_BAD_VALUE; status = B_BAD_VALUE;
else if (kernel)
memcpy(&flock, (struct flock*)argument, sizeof(struct flock));
else if (user_memcpy(&flock, (struct flock*)argument, else if (user_memcpy(&flock, (struct flock*)argument,
sizeof(struct flock)) != B_OK) sizeof(struct flock)) != B_OK)
status = B_BAD_ADDRESS; status = B_BAD_ADDRESS;
if (status != B_OK) { if (status != B_OK) {
put_fd(descriptor); put_fd(descriptor);
return status; return status;
@@ -6208,16 +6209,26 @@ common_fcntl(int fd, int op, size_t argument, bool kernel)
// no conflicting lock found, copy back the same struct // no conflicting lock found, copy back the same struct
// we were given except change type to F_UNLCK // we were given except change type to F_UNLCK
flock.l_type = F_UNLCK; flock.l_type = F_UNLCK;
status = user_memcpy((struct flock*)argument, &flock, if (kernel) {
sizeof(struct flock)); memcpy((struct flock*)argument, &flock,
sizeof(struct flock));
} else {
status = user_memcpy((struct flock*)argument,
&flock, sizeof(struct flock));
}
} else { } else {
// a conflicting lock was found, copy back its range and // a conflicting lock was found, copy back its range and
// type // type
if (normalizedLock.l_len == OFF_MAX) if (normalizedLock.l_len == OFF_MAX)
normalizedLock.l_len = 0; normalizedLock.l_len = 0;
status = user_memcpy((struct flock*)argument, if (kernel) {
&normalizedLock, sizeof(struct flock)); memcpy((struct flock*)argument,
&normalizedLock, sizeof(struct flock));
} else {
status = user_memcpy((struct flock*)argument,
&normalizedLock, sizeof(struct flock));
}
} }
} }
} else } else