diff options
Diffstat (limited to 'sys/kern/uipc_shm.c')
-rw-r--r-- | sys/kern/uipc_shm.c | 38 |
1 files changed, 32 insertions, 6 deletions
diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index a2146b9..0657787 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -57,6 +57,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/uio.h> #include <sys/signal.h> +#include <sys/jail.h> #include <sys/ktrace.h> #include <sys/lock.h> #include <sys/malloc.h> @@ -687,6 +688,8 @@ kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode, struct shmfd *shmfd; struct file *fp; char *path; + const char *pr_path; + size_t pr_pathlen; Fnv32_t fnv; mode_t cmode; int fd, error; @@ -723,13 +726,19 @@ kern_shm_open(struct thread *td, const char *userpath, int flags, mode_t mode, shmfd = shm_alloc(td->td_ucred, cmode); } else { path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); - error = copyinstr(userpath, path, MAXPATHLEN, NULL); + pr_path = td->td_ucred->cr_prison->pr_path; + + /* Construct a full pathname for jailed callers. */ + pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 + : strlcpy(path, pr_path, MAXPATHLEN); + error = copyinstr(userpath, path + pr_pathlen, + MAXPATHLEN - pr_pathlen, NULL); #ifdef KTRACE if (error == 0 && KTRPOINT(curthread, KTR_NAMEI)) ktrnamei(path); #endif /* Require paths to start with a '/' character. */ - if (error == 0 && path[0] != '/') + if (error == 0 && path[pr_pathlen] != '/') error = EINVAL; if (error) { fdclose(td, fp, fd); @@ -823,11 +832,17 @@ int sys_shm_unlink(struct thread *td, struct shm_unlink_args *uap) { char *path; + const char *pr_path; + size_t pr_pathlen; Fnv32_t fnv; int error; path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - error = copyinstr(uap->path, path, MAXPATHLEN, NULL); + pr_path = td->td_ucred->cr_prison->pr_path; + pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 + : strlcpy(path, pr_path, MAXPATHLEN); + error = copyinstr(uap->path, path + pr_pathlen, MAXPATHLEN - pr_pathlen, + NULL); if (error) { free(path, M_TEMP); return (error); @@ -1060,7 +1075,9 @@ shm_unmap(struct file *fp, void *mem, size_t size) static int shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) { + const char *path, *pr_path; struct shmfd *shmfd; + size_t pr_pathlen; kif->kf_type = KF_TYPE_SHM; shmfd = fp->f_data; @@ -1071,9 +1088,18 @@ shm_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) kif->kf_un.kf_file.kf_file_size = shmfd->shm_size; if (shmfd->shm_path != NULL) { sx_slock(&shm_dict_lock); - if (shmfd->shm_path != NULL) - strlcpy(kif->kf_path, shmfd->shm_path, - sizeof(kif->kf_path)); + if (shmfd->shm_path != NULL) { + path = shmfd->shm_path; + pr_path = curthread->td_ucred->cr_prison->pr_path; + if (strcmp(pr_path, "/") != 0) { + /* Return the jail-rooted pathname. */ + pr_pathlen = strlen(pr_path); + if (strncmp(path, pr_path, pr_pathlen) == 0 && + path[pr_pathlen] == '/') + path += pr_pathlen; + } + strlcpy(kif->kf_path, path, sizeof(kif->kf_path)); + } sx_sunlock(&shm_dict_lock); } return (0); |