summaryrefslogtreecommitdiffstats
path: root/selinux-apply-different-permission-to-ptrace-child.patch
diff options
context:
space:
mode:
authorJustin M. Forbes <jforbes@redhat.com>2012-04-09 16:40:04 -0500
committerJustin M. Forbes <jforbes@redhat.com>2012-04-09 16:40:04 -0500
commit1d7d6c12f3998ded631f92f6dccb997e1776a5c6 (patch)
treede0edce04ae5c6957e2eae6e1fb36676f2708ec9 /selinux-apply-different-permission-to-ptrace-child.patch
parent232e1a44c9753a19cc105aa7ab0b6767e3db1919 (diff)
downloadkernel-1d7d6c12f3998ded631f92f6dccb997e1776a5c6.tar.gz
kernel-1d7d6c12f3998ded631f92f6dccb997e1776a5c6.tar.xz
kernel-1d7d6c12f3998ded631f92f6dccb997e1776a5c6.zip
- SELinux apply a different permission to ptrace a child vs non-child
- Reenable debug
Diffstat (limited to 'selinux-apply-different-permission-to-ptrace-child.patch')
-rw-r--r--selinux-apply-different-permission-to-ptrace-child.patch162
1 files changed, 162 insertions, 0 deletions
diff --git a/selinux-apply-different-permission-to-ptrace-child.patch b/selinux-apply-different-permission-to-ptrace-child.patch
new file mode 100644
index 000000000..90baad840
--- /dev/null
+++ b/selinux-apply-different-permission-to-ptrace-child.patch
@@ -0,0 +1,162 @@
+Some applications, like gdb, are able to ptrace both children or other
+completely unrelated tasks. We would like to be able to discern these two
+things and to be able to allow gdb to ptrace it's children, but not to be
+able to ptrace unrelated tasks for security reasons.
+
+Upstream is a bit weary of this patch as it may be incomplete. They are
+not fundamentally opposed to the patch, I was just ask to see if I could
+flush out any needed refinement in Fedora where we already had the
+problem. We may find that we need to emulate the YAMA non-child
+registration module in order to completely deal with 'normal' ptrace on
+a system. At the moment however, this patch will at least let us get
+gdb working for many users in Fedora (See fedora-devel-list for a
+discussion of the current issues people are complaining about in F17
+without this)
+
+---
+
+ security/selinux/hooks.c | 38 +++++++++++++++++++++++++++++++++++
+ security/selinux/include/classmap.h | 2 +-
+ security/selinux/include/security.h | 2 ++
+ security/selinux/selinuxfs.c | 3 ++-
+ security/selinux/ss/services.c | 3 +++
+ 5 files changed, 46 insertions(+), 2 deletions(-)
+
+diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
+index 1a4acf4..b226f26 100644
+--- a/security/selinux/hooks.c
++++ b/security/selinux/hooks.c
+@@ -1805,6 +1805,39 @@ static inline u32 open_file_to_av(struct file *file)
+
+ /* Hook functions begin here. */
+
++/**
++ * task_is_descendant - walk up a process family tree looking for a match
++ * @parent: the process to compare against while walking up from child
++ * @child: the process to start from while looking upwards for parent
++ *
++ * Returns 1 if child is a descendant of parent, 0 if not.
++ */
++static int task_is_descendant(struct task_struct *parent,
++ struct task_struct *child)
++{
++ int rc = 0;
++ struct task_struct *walker = child;
++
++ if (!parent || !child)
++ return 0;
++
++ rcu_read_lock();
++ if (!thread_group_leader(parent))
++ parent = rcu_dereference(parent->group_leader);
++ while (walker->pid > 0) {
++ if (!thread_group_leader(walker))
++ walker = rcu_dereference(walker->group_leader);
++ if (walker == parent) {
++ rc = 1;
++ break;
++ }
++ walker = rcu_dereference(walker->real_parent);
++ }
++ rcu_read_unlock();
++
++ return rc;
++}
++
+ static int selinux_ptrace_access_check(struct task_struct *child,
+ unsigned int mode)
+ {
+@@ -1820,6 +1853,9 @@ static int selinux_ptrace_access_check(struct task_struct *child,
+ return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
+ }
+
++
++ if (selinux_policycap_ptrace_child && task_is_descendant(current, child))
++ return current_has_perm(child, PROCESS__PTRACE_CHILD);
+ return current_has_perm(child, PROCESS__PTRACE);
+ }
+
+@@ -1831,6 +1867,8 @@ static int selinux_ptrace_traceme(struct task_struct *parent)
+ if (rc)
+ return rc;
+
++ if (selinux_policycap_ptrace_child && task_is_descendant(parent, current))
++ return task_has_perm(parent, current, PROCESS__PTRACE_CHILD);
+ return task_has_perm(parent, current, PROCESS__PTRACE);
+ }
+
+diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
+index 39e678c..72c08b9 100644
+--- a/security/selinux/include/classmap.h
++++ b/security/selinux/include/classmap.h
+@@ -29,7 +29,7 @@ struct security_class_mapping secclass_map[] = {
+ "getattr", "setexec", "setfscreate", "noatsecure", "siginh",
+ "setrlimit", "rlimitinh", "dyntransition", "setcurrent",
+ "execmem", "execstack", "execheap", "setkeycreate",
+- "setsockcreate", NULL } },
++ "setsockcreate", "ptrace_child", NULL } },
+ { "system",
+ { "ipc_info", "syslog_read", "syslog_mod",
+ "syslog_console", "module_request", NULL } },
+diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
+index dde2005..ac14b0a 100644
+--- a/security/selinux/include/security.h
++++ b/security/selinux/include/security.h
+@@ -68,12 +68,14 @@ extern int selinux_enabled;
+ enum {
+ POLICYDB_CAPABILITY_NETPEER,
+ POLICYDB_CAPABILITY_OPENPERM,
++ POLICYDB_CAPABILITY_PTRACE_CHILD,
+ __POLICYDB_CAPABILITY_MAX
+ };
+ #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
+
+ extern int selinux_policycap_netpeer;
+ extern int selinux_policycap_openperm;
++extern int selinux_policycap_ptrace_child;
+
+ /*
+ * type_datum properties
+diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
+index 4e93f9e..3379765 100644
+--- a/security/selinux/selinuxfs.c
++++ b/security/selinux/selinuxfs.c
+@@ -44,7 +44,8 @@
+ /* Policy capability filenames */
+ static char *policycap_names[] = {
+ "network_peer_controls",
+- "open_perms"
++ "open_perms",
++ "ptrace_child",
+ };
+
+ unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
+diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
+index 9b7e7ed..4d12a6e 100644
+--- a/security/selinux/ss/services.c
++++ b/security/selinux/ss/services.c
+@@ -72,6 +72,7 @@
+
+ int selinux_policycap_netpeer;
+ int selinux_policycap_openperm;
++int selinux_policycap_ptrace_child;
+
+ static DEFINE_RWLOCK(policy_rwlock);
+
+@@ -1812,6 +1813,8 @@ static void security_load_policycaps(void)
+ POLICYDB_CAPABILITY_NETPEER);
+ selinux_policycap_openperm = ebitmap_get_bit(&policydb.policycaps,
+ POLICYDB_CAPABILITY_OPENPERM);
++ selinux_policycap_ptrace_child = ebitmap_get_bit(&policydb.policycaps,
++ POLICYDB_CAPABILITY_PTRACE_CHILD);
+ }
+
+ static int security_preserve_bools(struct policydb *p);
+
+
+
+
+_______________________________________________
+kernel mailing list
+kernel@lists.fedoraproject.org
+https://admin.fedoraproject.org/mailman/listinfo/kernel