Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_shm.c
Show First 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
shm_write(struct file *fp, struct uio *uio, struct ucred *active_cred, | shm_write(struct file *fp, struct uio *uio, struct ucred *active_cred, | ||||
int flags, struct thread *td) | int flags, struct thread *td) | ||||
{ | { | ||||
struct shmfd *shmfd; | struct shmfd *shmfd; | ||||
void *rl_cookie; | void *rl_cookie; | ||||
int error; | int error; | ||||
off_t size; | |||||
kib: The type cannot be size_t, it should be off_t, otherwise it wraps on 32bit arches. | |||||
shmfd = fp->f_data; | shmfd = fp->f_data; | ||||
#ifdef MAC | #ifdef MAC | ||||
error = mac_posixshm_check_write(active_cred, fp->f_cred, shmfd); | error = mac_posixshm_check_write(active_cred, fp->f_cred, shmfd); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
#endif | #endif | ||||
foffset_lock_uio(fp, uio, flags); | foffset_lock_uio(fp, uio, flags); | ||||
if (uio->uio_resid > OFF_MAX - uio->uio_offset) { | |||||
Not Done Inline ActionsI think this should be checked for overflow. kib: I think this should be checked for overflow. | |||||
Done Inline ActionsSure, this seems like a good idea. I guess for SHM_GROW_ON_WRITE we should probably return EFBIG on error, and if we're not growing from write we just clamp it to shmfd->shm_size? Previously we would've overflowed when grabbing the rangelock, but I suppose we're more likely to overflow in the !FOF_OFFSET case than offset-supplied. kevans: Sure, this seems like a good idea. I guess for SHM_GROW_ON_WRITE we should probably return… | |||||
/* | |||||
* Overflow is only an error if we're supposed to expand on | |||||
* write. Otherwise, we'll just truncate the write to the | |||||
* size of the file, which can only grow up to OFF_MAX. | |||||
*/ | |||||
if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0) { | |||||
foffset_unlock_uio(fp, uio, flags); | |||||
return (EFBIG); | |||||
} | |||||
size = shmfd->shm_size; | |||||
} else { | |||||
size = uio->uio_offset + uio->uio_resid; | |||||
} | |||||
if ((flags & FOF_OFFSET) == 0) { | if ((flags & FOF_OFFSET) == 0) { | ||||
rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, | rl_cookie = rangelock_wlock(&shmfd->shm_rl, 0, OFF_MAX, | ||||
&shmfd->shm_mtx); | &shmfd->shm_mtx); | ||||
} else { | } else { | ||||
rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset, | rl_cookie = rangelock_wlock(&shmfd->shm_rl, uio->uio_offset, | ||||
uio->uio_offset + uio->uio_resid, &shmfd->shm_mtx); | size, &shmfd->shm_mtx); | ||||
} | } | ||||
if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) | if ((shmfd->shm_seals & F_SEAL_WRITE) != 0) { | ||||
error = EPERM; | error = EPERM; | ||||
else | } else { | ||||
error = uiomove_object(shmfd->shm_object, shmfd->shm_size, uio); | error = 0; | ||||
if ((shmfd->shm_flags & SHM_GROW_ON_WRITE) != 0 && | |||||
size > shmfd->shm_size) { | |||||
VM_OBJECT_WLOCK(shmfd->shm_object); | |||||
error = shm_dotruncate_locked(shmfd, size, rl_cookie); | |||||
VM_OBJECT_WUNLOCK(shmfd->shm_object); | |||||
} | |||||
if (error == 0) | |||||
error = uiomove_object(shmfd->shm_object, | |||||
shmfd->shm_size, uio); | |||||
} | |||||
rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | rangelock_unlock(&shmfd->shm_rl, rl_cookie, &shmfd->shm_mtx); | ||||
foffset_unlock_uio(fp, uio, flags); | foffset_unlock_uio(fp, uio, flags); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
shm_truncate(struct file *fp, off_t length, struct ucred *active_cred, | shm_truncate(struct file *fp, off_t length, struct ucred *active_cred, | ||||
struct thread *td) | struct thread *td) | ||||
▲ Show 20 Lines • Show All 401 Lines • ▼ Show 20 Lines | kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, | ||||
struct shmfd *shmfd; | struct shmfd *shmfd; | ||||
struct file *fp; | struct file *fp; | ||||
char *path; | char *path; | ||||
void *rl_cookie; | void *rl_cookie; | ||||
Fnv32_t fnv; | Fnv32_t fnv; | ||||
mode_t cmode; | mode_t cmode; | ||||
int error, fd, initial_seals; | int error, fd, initial_seals; | ||||
if ((shmflags & ~SHM_ALLOW_SEALING) != 0) | if ((shmflags & ~(SHM_ALLOW_SEALING | SHM_GROW_ON_WRITE)) != 0) | ||||
return (EINVAL); | return (EINVAL); | ||||
initial_seals = F_SEAL_SEAL; | initial_seals = F_SEAL_SEAL; | ||||
if ((shmflags & SHM_ALLOW_SEALING) != 0) | if ((shmflags & SHM_ALLOW_SEALING) != 0) | ||||
initial_seals &= ~F_SEAL_SEAL; | initial_seals &= ~F_SEAL_SEAL; | ||||
#ifdef CAPABILITY_MODE | #ifdef CAPABILITY_MODE | ||||
/* | /* | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | #endif | ||||
if (error) { | if (error) { | ||||
fdclose(td, fp, fd); | fdclose(td, fp, fd); | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
shmfd->shm_flags = shmflags; | |||||
if (name != NULL) | if (name != NULL) | ||||
shmfd->shm_name = strdup(name, M_SHMFD); | shmfd->shm_name = strdup(name, M_SHMFD); | ||||
finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops); | finit(fp, FFLAGS(flags & O_ACCMODE), DTYPE_SHM, shmfd, &shm_ops); | ||||
td->td_retval[0] = fd; | td->td_retval[0] = fd; | ||||
fdrop(fp, td); | fdrop(fp, td); | ||||
▲ Show 20 Lines • Show All 664 Lines • Show Last 20 Lines |
The type cannot be size_t, it should be off_t, otherwise it wraps on 32bit arches.