Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/uipc_shm.c
| Show First 20 Lines • Show All 1,167 Lines • ▼ Show 20 Lines | kern_shm_open2(struct thread *td, const char *userpath, int flags, mode_t mode, | ||||
| if ((shmflags & ~(SHM_ALLOW_SEALING | SHM_GROW_ON_WRITE | | if ((shmflags & ~(SHM_ALLOW_SEALING | SHM_GROW_ON_WRITE | | ||||
| SHM_LARGEPAGE)) != 0) | SHM_LARGEPAGE)) != 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 | |||||
| /* | |||||
| * shm_open(2) is only allowed for anonymous objects. | |||||
| */ | |||||
| if (userpath != SHM_ANON) { | |||||
| if (CAP_TRACING(td)) | |||||
| ktrcapfail(CAPFAIL_NAMEI, userpath); | |||||
| if (IN_CAPABILITY_MODE(td)) | |||||
| return (ECAPMODE); | |||||
| } | |||||
| #endif | |||||
| AUDIT_ARG_FFLAGS(flags); | AUDIT_ARG_FFLAGS(flags); | ||||
| AUDIT_ARG_MODE(mode); | AUDIT_ARG_MODE(mode); | ||||
| if ((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR) | if ((flags & O_ACCMODE) != O_RDONLY && (flags & O_ACCMODE) != O_RDWR) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| if ((flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)) != 0) | if ((flags & ~(O_ACCMODE | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)) != 0) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| largepage = (shmflags & SHM_LARGEPAGE) != 0; | largepage = (shmflags & SHM_LARGEPAGE) != 0; | ||||
| if (largepage && !PMAP_HAS_LARGEPAGES) | if (largepage && !PMAP_HAS_LARGEPAGES) | ||||
| return (ENOTTY); | return (ENOTTY); | ||||
| /* | /* | ||||
| * Currently only F_SEAL_SEAL may be set when creating or opening shmfd. | * Currently only F_SEAL_SEAL may be set when creating or opening shmfd. | ||||
| * If the decision is made later to allow additional seals, care must be | * If the decision is made later to allow additional seals, care must be | ||||
| * taken below to ensure that the seals are properly set if the shmfd | * taken below to ensure that the seals are properly set if the shmfd | ||||
| * already existed -- this currently assumes that only F_SEAL_SEAL can | * already existed -- this currently assumes that only F_SEAL_SEAL can | ||||
| * be set and doesn't take further precautions to ensure the validity of | * be set and doesn't take further precautions to ensure the validity of | ||||
| * the seals being added with respect to current mappings. | * the seals being added with respect to current mappings. | ||||
| */ | */ | ||||
| if ((initial_seals & ~F_SEAL_SEAL) != 0) | if ((initial_seals & ~F_SEAL_SEAL) != 0) | ||||
| return (EINVAL); | return (EINVAL); | ||||
| if (userpath != SHM_ANON) { | |||||
| error = shm_copyin_path(td, userpath, &path); | |||||
| if (error != 0) | |||||
| return (error); | |||||
| #ifdef CAPABILITY_MODE | |||||
| /* | |||||
| * shm_open(2) is only allowed for anonymous objects. | |||||
| */ | |||||
| if (CAP_TRACING(td)) | |||||
| ktrcapfail(CAPFAIL_NAMEI, path); | |||||
| if (IN_CAPABILITY_MODE(td)) { | |||||
| free(path, M_SHMFD); | |||||
| return (ECAPMODE); | |||||
| } | |||||
| #endif | |||||
| AUDIT_ARG_UPATH1_CANON(path); | |||||
| } | |||||
| pdp = td->td_proc->p_pd; | pdp = td->td_proc->p_pd; | ||||
| cmode = (mode & ~pdp->pd_cmask) & ACCESSPERMS; | cmode = (mode & ~pdp->pd_cmask) & ACCESSPERMS; | ||||
| /* | /* | ||||
| * shm_open(2) created shm should always have O_CLOEXEC set, as mandated | * shm_open(2) created shm should always have O_CLOEXEC set, as mandated | ||||
| * by POSIX. We allow it to be unset here so that an in-kernel | * by POSIX. We allow it to be unset here so that an in-kernel | ||||
| * interface may be written as a thin layer around shm, optionally not | * interface may be written as a thin layer around shm, optionally not | ||||
| * setting CLOEXEC. For shm_open(2), O_CLOEXEC is set unconditionally | * setting CLOEXEC. For shm_open(2), O_CLOEXEC is set unconditionally | ||||
| * in sys_shm_open() to keep this implementation compliant. | * in sys_shm_open() to keep this implementation compliant. | ||||
| */ | */ | ||||
| error = falloc_caps(td, &fp, &fd, flags & O_CLOEXEC, fcaps); | error = falloc_caps(td, &fp, &fd, flags & O_CLOEXEC, fcaps); | ||||
| if (error) | if (error) { | ||||
| free(path, M_SHMFD); | |||||
| return (error); | return (error); | ||||
| } | |||||
| /* A SHM_ANON path pointer creates an anonymous object. */ | /* A SHM_ANON path pointer creates an anonymous object. */ | ||||
| if (userpath == SHM_ANON) { | if (userpath == SHM_ANON) { | ||||
| /* A read-only anonymous object is pointless. */ | /* A read-only anonymous object is pointless. */ | ||||
| if ((flags & O_ACCMODE) == O_RDONLY) { | if ((flags & O_ACCMODE) == O_RDONLY) { | ||||
| fdclose(td, fp, fd); | fdclose(td, fp, fd); | ||||
| fdrop(fp, td); | fdrop(fp, td); | ||||
| return (EINVAL); | return (EINVAL); | ||||
| } | } | ||||
| shmfd = shm_alloc(td->td_ucred, cmode, largepage); | shmfd = shm_alloc(td->td_ucred, cmode, largepage); | ||||
| shmfd->shm_seals = initial_seals; | shmfd->shm_seals = initial_seals; | ||||
| shmfd->shm_flags = shmflags; | shmfd->shm_flags = shmflags; | ||||
| } else { | } else { | ||||
| error = shm_copyin_path(td, userpath, &path); | |||||
| if (error != 0) { | |||||
| fdclose(td, fp, fd); | |||||
| fdrop(fp, td); | |||||
| return (error); | |||||
| } | |||||
| AUDIT_ARG_UPATH1_CANON(path); | |||||
| fnv = fnv_32_str(path, FNV1_32_INIT); | fnv = fnv_32_str(path, FNV1_32_INIT); | ||||
| sx_xlock(&shm_dict_lock); | sx_xlock(&shm_dict_lock); | ||||
| shmfd = shm_lookup(path, fnv); | shmfd = shm_lookup(path, fnv); | ||||
| if (shmfd == NULL) { | if (shmfd == NULL) { | ||||
| /* Object does not yet exist, create it if requested. */ | /* Object does not yet exist, create it if requested. */ | ||||
| if (flags & O_CREAT) { | if (flags & O_CREAT) { | ||||
| #ifdef MAC | #ifdef MAC | ||||
| error = mac_posixshm_check_create(td->td_ucred, | error = mac_posixshm_check_create(td->td_ucred, | ||||
| ▲ Show 20 Lines • Show All 938 Lines • Show Last 20 Lines | |||||