Page MenuHomeFreeBSD

D22977.id.diff
No OneTemporary

D22977.id.diff

Index: head/sys/compat/linux/linux_mmap.c
===================================================================
--- head/sys/compat/linux/linux_mmap.c
+++ head/sys/compat/linux/linux_mmap.c
@@ -62,7 +62,17 @@
static void linux_fixup_prot(struct thread *td, int *prot);
#endif
+static int
+linux_mmap_check_fp(struct file *fp, int flags, int prot, int maxprot)
+{
+ /* Linux mmap() just fails for O_WRONLY files */
+ if ((fp->f_flag & FREAD) == 0)
+ return (EACCES);
+
+ return (0);
+}
+
int
linux_mmap_common(struct thread *td, uintptr_t addr, size_t len, int prot,
int flags, int fd, off_t pos)
@@ -117,31 +127,6 @@
/* Linux does not check file descriptor when MAP_ANONYMOUS is set. */
fd = (bsd_flags & MAP_ANON) ? -1 : fd;
- if (fd != -1) {
- /*
- * Linux follows Solaris mmap(2) description:
- * The file descriptor fildes is opened with
- * read permission, regardless of the
- * protection options specified.
- */
-
- error = fget(td, fd, &cap_mmap_rights, &fp);
- if (error != 0)
- return (error);
- if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_DEV) {
- fdrop(fp, td);
- return (EINVAL);
- }
-
- /* Linux mmap() just fails for O_WRONLY files */
- if (!(fp->f_flag & FREAD)) {
- fdrop(fp, td);
- return (EACCES);
- }
-
- fdrop(fp, td);
- }
-
if (flags & LINUX_MAP_GROWSDOWN) {
/*
* The Linux MAP_GROWSDOWN option does not limit auto
@@ -211,13 +196,15 @@
*/
if (addr != 0 && (bsd_flags & MAP_FIXED) == 0 &&
(bsd_flags & MAP_EXCL) == 0) {
- error = kern_mmap(td, addr, len, prot,
- bsd_flags | MAP_FIXED | MAP_EXCL, fd, pos);
+ error = kern_mmap_fpcheck(td, addr, len, prot,
+ bsd_flags | MAP_FIXED | MAP_EXCL, fd, pos,
+ linux_mmap_check_fp);
if (error == 0)
goto out;
}
- error = kern_mmap(td, addr, len, prot, bsd_flags, fd, pos);
+ error = kern_mmap_fpcheck(td, addr, len, prot, bsd_flags, fd, pos,
+ linux_mmap_check_fp);
out:
LINUX_CTR2(mmap2, "return: %d (%p)", error, td->td_retval[0]);
Index: head/sys/sys/syscallsubr.h
===================================================================
--- head/sys/sys/syscallsubr.h
+++ head/sys/sys/syscallsubr.h
@@ -63,6 +63,8 @@
struct thr_param;
struct uio;
+typedef int (*mmap_check_fp_fn)(struct file *, int, int, int);
+
int kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg,
size_t buflen, size_t path_max);
int kern_accept(struct thread *td, int s, struct sockaddr **name,
@@ -179,6 +181,9 @@
size_t len);
int kern_mmap(struct thread *td, uintptr_t addr, size_t len, int prot,
int flags, int fd, off_t pos);
+int kern_mmap_fpcheck(struct thread *td, uintptr_t addr, size_t len,
+ int prot, int flags, int fd, off_t pos,
+ mmap_check_fp_fn check_fp_fn);
int kern_mmap_maxprot(struct proc *p, int prot);
int kern_mprotect(struct thread *td, uintptr_t addr, size_t size, int prot);
int kern_msgctl(struct thread *, int, int, struct msqid_ds *);
Index: head/sys/vm/vm_mmap.c
===================================================================
--- head/sys/vm/vm_mmap.c
+++ head/sys/vm/vm_mmap.c
@@ -199,6 +199,18 @@
kern_mmap(struct thread *td, uintptr_t addr0, size_t len, int prot, int flags,
int fd, off_t pos)
{
+
+ return (kern_mmap_fpcheck(td, addr, len, prot, flags, fd, pos, NULL));
+}
+
+/*
+ * When mmap'ing a file, check_fp_fn may be used for the caller to do any
+ * last-minute validation based on the referenced file in a non-racy way.
+ */
+int
+kern_mmap_fpcheck(struct thread *td, uintptr_t addr0, size_t len, int prot,
+ int flags, int fd, off_t pos, mmap_check_fp_fn check_fp_fn)
+{
struct vmspace *vms;
struct file *fp;
struct proc *p;
@@ -394,7 +406,12 @@
error = EINVAL;
goto done;
}
-
+ if (check_fp_fn != NULL) {
+ error = check_fp_fn(fp, prot, max_prot & cap_maxprot,
+ flags);
+ if (error != 0)
+ goto done;
+ }
/* This relies on VM_PROT_* matching PROT_*. */
error = fo_mmap(fp, &vms->vm_map, &addr, size, prot,
max_prot & cap_maxprot, flags, pos, td);

File Metadata

Mime Type
text/plain
Expires
Fri, Aug 28, 6:13 AM (12 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37440080
Default Alt Text
D22977.id.diff (3 KB)

Event Timeline