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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user