Browse Source

drivers/char/hpet.c: allow user controlled mmap for user processes

The CONFIG_HPET_MMAP Kconfig option exposes the memory map of the HPET
registers to userspace.  The Kconfig help points out that in some cases
this can be a security risk as some systems may erroneously configure the
map such that additional data is exposed to userspace.

This is a problem for distributions -- some users want the MMAP
functionality but it comes with a significant security risk.  In an effort
to mitigate this risk, and due to the low number of users of the MMAP
functionality, I've introduced a kernel parameter, hpet_mmap_enable, that
is required in order to actually have the HPET MMAP exposed.

Signed-off-by: Prarit Bhargava <prarit@redhat.com>
Acked-by: Matt Wilson <msw@amazon.com>
Signed-off-by: Clemens Ladisch <clemens@ladisch.de>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Prarit Bhargava 11 years ago
parent
commit
3d035f5806
3 changed files with 33 additions and 4 deletions
  1. 3 0
      Documentation/kernel-parameters.txt
  2. 8 2
      drivers/char/Kconfig
  3. 22 2
      drivers/char/hpet.c

+ 3 - 0
Documentation/kernel-parameters.txt

@@ -1070,6 +1070,9 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 				VIA, nVidia)
 				VIA, nVidia)
 			verbose: show contents of HPET registers during setup
 			verbose: show contents of HPET registers during setup
 
 
+	hpet_mmap=	[X86, HPET_MMAP] Allow userspace to mmap HPET
+			registers.  Default set by CONFIG_HPET_MMAP_DEFAULT.
+
 	hugepages=	[HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
 	hugepages=	[HW,X86-32,IA-64] HugeTLB pages to allocate at boot.
 	hugepagesz=	[HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
 	hugepagesz=	[HW,IA-64,PPC,X86-64] The size of the HugeTLB pages.
 			On x86-64 and powerpc, this option can be specified
 			On x86-64 and powerpc, this option can be specified

+ 8 - 2
drivers/char/Kconfig

@@ -522,10 +522,16 @@ config HPET_MMAP
 	  If you say Y here, user applications will be able to mmap
 	  If you say Y here, user applications will be able to mmap
 	  the HPET registers.
 	  the HPET registers.
 
 
+config HPET_MMAP_DEFAULT
+	bool "Enable HPET MMAP access by default"
+	default y
+	depends on HPET_MMAP
+	help
 	  In some hardware implementations, the page containing HPET
 	  In some hardware implementations, the page containing HPET
 	  registers may also contain other things that shouldn't be
 	  registers may also contain other things that shouldn't be
-	  exposed to the user.  If this applies to your hardware,
-	  say N here.
+	  exposed to the user.  This option selects the default (if
+	  kernel parameter hpet_mmap is not set) user access to the
+	  registers for applications that require it.
 
 
 config HANGCHECK_TIMER
 config HANGCHECK_TIMER
 	tristate "Hangcheck timer"
 	tristate "Hangcheck timer"

+ 22 - 2
drivers/char/hpet.c

@@ -367,12 +367,29 @@ static unsigned int hpet_poll(struct file *file, poll_table * wait)
 	return 0;
 	return 0;
 }
 }
 
 
+#ifdef CONFIG_HPET_MMAP
+#ifdef CONFIG_HPET_MMAP_DEFAULT
+static int hpet_mmap_enabled = 1;
+#else
+static int hpet_mmap_enabled = 0;
+#endif
+
+static __init int hpet_mmap_enable(char *str)
+{
+	get_option(&str, &hpet_mmap_enabled);
+	pr_info("HPET mmap %s\n", hpet_mmap_enabled ? "enabled" : "disabled");
+	return 1;
+}
+__setup("hpet_mmap", hpet_mmap_enable);
+
 static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 {
 {
-#ifdef	CONFIG_HPET_MMAP
 	struct hpet_dev *devp;
 	struct hpet_dev *devp;
 	unsigned long addr;
 	unsigned long addr;
 
 
+	if (!hpet_mmap_enabled)
+		return -EACCES;
+
 	devp = file->private_data;
 	devp = file->private_data;
 	addr = devp->hd_hpets->hp_hpet_phys;
 	addr = devp->hd_hpets->hp_hpet_phys;
 
 
@@ -381,10 +398,13 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
 
 
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
 	return vm_iomap_memory(vma, addr, PAGE_SIZE);
 	return vm_iomap_memory(vma, addr, PAGE_SIZE);
+}
 #else
 #else
+static int hpet_mmap(struct file *file, struct vm_area_struct *vma)
+{
 	return -ENOSYS;
 	return -ENOSYS;
-#endif
 }
 }
+#endif
 
 
 static int hpet_fasync(int fd, struct file *file, int on)
 static int hpet_fasync(int fd, struct file *file, int on)
 {
 {