diff --git a/fs/exec.c b/fs/exec.c
index 8dcadcf..d08b205 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1525,6 +1525,11 @@ static int do_execve_common(const char *filename,
 	if (IS_ERR(file))
 		goto out_unmark;
 
+	if (gr_ptrace_readexec(file, bprm->unsafe)) {
+		retval = -EPERM;
+		goto out_file;
+	}
+
 	sched_exec();
 
 	bprm->file = file;
diff --git a/grsecurity/Kconfig b/grsecurity/Kconfig
index 4639511..fbe6950d9 100644
--- a/grsecurity/Kconfig
+++ b/grsecurity/Kconfig
@@ -136,6 +136,7 @@ config GRKERNSEC_HIGH
 	select GRKERNSEC_AUDIT_MOUNT
 	select GRKERNSEC_MODHARDEN if (MODULES)
 	select GRKERNSEC_HARDEN_PTRACE
+	select GRKERNSEC_PTRACE_READEXEC
 	select GRKERNSEC_VM86 if (X86_32)
 	select GRKERNSEC_KERN_LOCKOUT if (X86 || ARM || PPC || SPARC)
 	select PAX
@@ -798,6 +799,21 @@ config GRKERNSEC_HARDEN_PTRACE
 	  option is enabled, a sysctl option with name "harden_ptrace" is
 	  created.
 
+config GRKERNSEC_PTRACE_READEXEC
+	bool "Require read access to ptrace sensitive binaries"
+	help
+	  If you say Y here, read permission will be required by any unprivileged
+	  process to ptrace suid/sgid binaries.  Note that the ability to
+	  ptrace privileged binaries and retain that binary's privilege is
+	  already not possible.  This option is useful in environments that
+	  remove the read bits (e.g. file mode 4711) from suid binaries to
+	  prevent infoleaking of their contents.  What this option adds
+	  is consistency to the use of that file mode, as the binary could normally
+	  be read out when run without privileges while ptracing.
+
+	  If the sysctl option is enabled, a sysctl option with name "ptrace_readexec"
+	  is created.
+
 config GRKERNSEC_SETXID
 	bool "Enforce consistent multithreaded privileges"
 	help
diff --git a/grsecurity/grsec_init.c b/grsecurity/grsec_init.c
index cb8e5a1..01ddde4 100644
--- a/grsecurity/grsec_init.c
+++ b/grsecurity/grsec_init.c
@@ -7,6 +7,7 @@
 #include <linux/percpu.h>
 #include <linux/module.h>
 
+int grsec_enable_ptrace_readexec;
 int grsec_enable_setxid;
 int grsec_enable_brute;
 int grsec_enable_link;
@@ -160,6 +161,9 @@ grsecurity_init(void)
 	grsec_enable_group = 1;
 	grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
 #endif
+#ifdef CONFIG_GRKERNSEC_PTRACE_READEXEC
+	grsec_enable_ptrace_readexec = 1;
+#endif
 #ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
 	grsec_enable_chdir = 1;
 #endif
diff --git a/grsecurity/grsec_ptrace.c b/grsecurity/grsec_ptrace.c
index 472c1d6..f7f29aa 100644
--- a/grsecurity/grsec_ptrace.c
+++ b/grsecurity/grsec_ptrace.c
@@ -1,7 +1,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/grinternal.h>
-#include <linux/grsecurity.h>
+#include <linux/security.h>
 
 void
 gr_audit_ptrace(struct task_struct *task)
@@ -12,3 +12,19 @@ gr_audit_ptrace(struct task_struct *task)
 #endif
 	return;
 }
+
+int
+gr_ptrace_readexec(struct file *file, int unsafe_flags)
+{
+#ifdef CONFIG_GRKERNSEC_PTRACE_READEXEC
+	const struct dentry *dentry = file->f_path.dentry;
+	const struct vfsmount *mnt = file->f_path.mnt;
+
+	if (grsec_enable_ptrace_readexec && (unsafe_flags & LSM_UNSAFE_PTRACE) && 
+	    (inode_permission(dentry->d_inode, MAY_READ) || !gr_acl_handle_open(dentry, mnt, MAY_READ))) {
+		gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_READEXEC_MSG, dentry, mnt);
+		return -EACCES;
+	}
+#endif
+	return 0;
+}
diff --git a/grsecurity/grsec_sysctl.c b/grsecurity/grsec_sysctl.c
index bceef2f..a1aedd7 100644
--- a/grsecurity/grsec_sysctl.c
+++ b/grsecurity/grsec_sysctl.c
@@ -61,6 +61,15 @@ struct ctl_table grsecurity_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 #endif
+#ifdef CONFIG_GRKERNSEC_PTRACE_READEXEC
+	{
+		.procname	= "ptrace_readexec",
+		.data		= &grsec_enable_ptrace_readexec,
+		.maxlen		= sizeof(int),
+		.mode		= 0600,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
 #ifdef CONFIG_GRKERNSEC_SETXID
 	{
 		.procname	= "consistent_setxid",
diff --git a/include/linux/grinternal.h b/include/linux/grinternal.h
index 60cda84..da390f1 100644
--- a/include/linux/grinternal.h
+++ b/include/linux/grinternal.h
@@ -34,6 +34,7 @@ char *gr_to_filename2(const struct dentry *dentry,
 char *gr_to_filename3(const struct dentry *dentry,
 			    const struct vfsmount *mnt);
 
+extern int grsec_enable_ptrace_readexec;
 extern int grsec_enable_harden_ptrace;
 extern int grsec_enable_link;
 extern int grsec_enable_fifo;
diff --git a/include/linux/grmsg.h b/include/linux/grmsg.h
index 9d5fd4a..cf49370 100644
--- a/include/linux/grmsg.h
+++ b/include/linux/grmsg.h
@@ -105,4 +105,5 @@
 #define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by "
 #define GR_VM86_MSG "denied use of vm86 by "
 #define GR_PTRACE_AUDIT_MSG "process %.950s(%.16s:%d) attached to via ptrace by "
+#define GR_PTRACE_READEXEC_MSG "denied ptrace of unreadable suid/sgid binary %.950s by "
 #define GR_INIT_TRANSFER_MSG "persistent special role transferred privilege to init by "
diff --git a/include/linux/grsecurity.h b/include/linux/grsecurity.h
index 4620f36..1ca3931 100644
--- a/include/linux/grsecurity.h
+++ b/include/linux/grsecurity.h
@@ -213,6 +213,8 @@ int gr_handle_rofs_blockwrite(struct dentry *dentry, struct vfsmount *mnt, int a
 void gr_audit_ptrace(struct task_struct *task);
 dev_t gr_get_dev_from_dentry(struct dentry *dentry);
 
+int gr_ptrace_readexec(struct file *file, int unsafe_flags);
+
 #ifdef CONFIG_GRKERNSEC
 void task_grsec_rbac(struct seq_file *m, struct task_struct *p);
 void gr_handle_vm86(void);
