mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 08:43:19 -04:00
posixshm: Fix range locking in shm_write()
There is a somewhat strange case where when writing to a POSIX shm object, the object is not allowed to grow, and the I/O offset+length overflows. In that case we simply truncate the I/O to the object size. Later we write-lock the range [offset, objsize). However, we were not checking whether offset > objsize, in which case we're writing zero bytes but locking an invalid range. Modify the range locking in shm_write() to take this possibility into account. While here, rename a variable to make its purpose a bit more clear, and add an assertion against negative offsets (which is supposed to be enforced by the caller of fo_write for I/O to files that aren't character devices). Reported by: syzkaller Reviewed by: kevans, kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D49673
This commit is contained in:
parent
da05ca9ab6
commit
82d8c609cf
1 changed files with 11 additions and 6 deletions
|
|
@ -481,7 +481,10 @@ shm_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
|||
struct shmfd *shmfd;
|
||||
void *rl_cookie;
|
||||
int error;
|
||||
off_t size;
|
||||
off_t newsize;
|
||||
|
||||
KASSERT((flags & FOF_OFFSET) == 0 || uio->uio_offset >= 0,
|
||||
("%s: negative offset", __func__));
|
||||
|
||||
shmfd = fp->f_data;
|
||||
#ifdef MAC
|
||||
|
|
@ -503,21 +506,23 @@ shm_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
|
|||
return (EFBIG);
|
||||
}
|
||||
|
||||
size = shmfd->shm_size;
|
||||
newsize = atomic_load_64(&shmfd->shm_size);
|
||||
} else {
|
||||
size = uio->uio_offset + uio->uio_resid;
|
||||
newsize = uio->uio_offset + uio->uio_resid;
|
||||
}
|
||||
if ((flags & FOF_OFFSET) == 0)
|
||||
rl_cookie = shm_rangelock_wlock(shmfd, 0, OFF_MAX);
|
||||
else
|
||||
rl_cookie = shm_rangelock_wlock(shmfd, uio->uio_offset, size);
|
||||
rl_cookie = shm_rangelock_wlock(shmfd, uio->uio_offset,
|
||||
MAX(newsize, uio->uio_offset));
|
||||
if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) {
|
||||
error = EPERM;
|
||||
} else {
|
||||
error = 0;
|
||||
if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 &&
|
||||
size > shmfd->shm_size) {
|
||||
error = shm_dotruncate_cookie(shmfd, size, rl_cookie);
|
||||
newsize > shmfd->shm_size) {
|
||||
error = shm_dotruncate_cookie(shmfd, newsize,
|
||||
rl_cookie);
|
||||
}
|
||||
if (error == 0)
|
||||
error = uiomove_object(shmfd->shm_object,
|
||||
|
|
|
|||
Loading…
Reference in a new issue