Add the SELinux access control implementation for the new kdbus LSM
hooks using the new kdbus object class and the following permissions:

 [NOTE: permissions below are based on kdbus code from Aug 2015]

 * kdbus:impersonate
   Send a different security label to kdbus peers.
 * kdbus:fakecreds
   Send different DAC credentials to kdbus peers.
 * kdbus:fakepids
   Send a different PID to kdbus peers.
 * kdbus:owner
   Act as a kdbus bus owner.
 * kdbus:privileged
   Act as a privileged endpoint.
 * kdbus:activator
   Act as a kdbus activator.
 * kdbus:monitor
   Act as a kdbus monitor.
 * kdbus:policy_holder
   Act as a kdbus policy holder.
 * kdbus:connect
   Create a new kdbus connection.
 * kdbus:own
   Own a kdbus service name.
 * kdbus:talk
   Talk between two kdbus endpoints.
 * kdbus:see
   See another kdbus endpoint.
 * kdbus:see_name
   See a kdbus service name.
 * kdbus:see_notification
   See a kdbus notification.

Signed-off-by: Paul Moore <pmo...@redhat.com>

---
ChangeLog:
- v3
 * Ported to the 4.3-rc4 based kdbus tree
 * Fix the missing NULL terminator in the kdbus obj class definition
- v2
 * Add the selinux_kdbus_init_inode() hook
 * Add some very basic info on the permissions to the description
 * Add kdbus service name auditing in the AVC records
- v1
 * Initial draft
---
 security/selinux/hooks.c            |  153 +++++++++++++++++++++++++++++++++++
 security/selinux/include/classmap.h |    4 +
 2 files changed, 155 insertions(+), 2 deletions(-)

diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index e4369d8..5581990 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -9,8 +9,10 @@
  *           James Morris <jmor...@redhat.com>
  *
  *  Copyright (C) 2001,2002 Networks Associates Technology, Inc.
- *  Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmor...@redhat.com>
- *                                        Eric Paris <epa...@redhat.com>
+ *  Copyright (C) 2003-2008,2015 Red Hat, Inc.
+ *                                     James Morris <jmor...@redhat.com>
+ *                                     Eric Paris <epa...@redhat.com>
+ *                                     Paul Moore <p...@paul-moore.com>
  *  Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
  *                         <dgoed...@trustedcs.com>
  *  Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P.
@@ -2035,6 +2037,143 @@ static int selinux_binder_transfer_file(struct 
task_struct *from,
                            &ad);
 }
 
+static int selinux_kdbus_conn_new(const struct cred *creds,
+                                 const struct kdbus_creds *fake_creds,
+                                 const struct kdbus_pids *fake_pids,
+                                 const char *fake_seclabel,
+                                 bool owner, bool privileged,
+                                 bool is_activator, bool is_monitor,
+                                 bool is_policy_holder)
+{
+       int rc;
+       u32 tsid = current_sid();
+       u32 av = KDBUS__CONNECT;
+
+       if (fake_creds)
+               av |= KDBUS__FAKECREDS;
+       if (fake_pids)
+               av |= KDBUS__FAKEPIDS;
+       if (owner)
+               av |= KDBUS__OWNER;
+       if (privileged)
+               av |= KDBUS__PRIVILEGED;
+       if (is_activator)
+               av |= KDBUS__ACTIVATOR;
+       if (is_monitor)
+               av |= KDBUS__MONITOR;
+       if (is_policy_holder)
+               av |= KDBUS__POLICY_HOLDER;
+
+       rc = avc_has_perm(tsid, cred_sid(creds), SECCLASS_KDBUS, av, NULL);
+       if (rc)
+               return rc;
+
+       if (fake_seclabel) {
+               u32 sid;
+               if (security_context_to_sid(fake_seclabel,
+                                           strlen(fake_seclabel),
+                                           &sid, GFP_KERNEL))
+                       return -EINVAL;
+
+               rc = avc_has_perm(tsid, sid,
+                                 SECCLASS_KDBUS, KDBUS__IMPERSONATE, NULL);
+       }
+
+       return rc;
+}
+
+static int selinux_kdbus_own_name(const struct cred *creds, const char *name)
+{
+       int rc;
+       u32 name_sid;
+       struct common_audit_data ad;
+
+       rc = security_kdbus_sid(name, &name_sid);
+       if (rc)
+               return rc;
+
+       ad.type = LSM_AUDIT_DATA_KDBUS;
+       ad.u.kdbus_name = name;
+
+       return avc_has_perm(cred_sid(creds), name_sid,
+                           SECCLASS_KDBUS, KDBUS__OWN, &ad);
+}
+
+static int selinux_kdbus_conn_talk(const struct cred *creds,
+                                  const struct cred *creds_to)
+{
+       return avc_has_perm(cred_sid(creds), cred_sid(creds_to),
+                           SECCLASS_KDBUS, KDBUS__TALK, NULL);
+}
+
+static int selinux_kdbus_conn_see(const struct cred *creds,
+                                 const struct cred *creds_whom)
+{
+       return avc_has_perm(cred_sid(creds), cred_sid(creds_whom),
+                           SECCLASS_KDBUS, KDBUS__SEE, NULL);
+}
+
+static int selinux_kdbus_conn_see_name(const struct cred *creds,
+                                      const char *name)
+{
+       int rc;
+       u32 name_sid;
+       struct common_audit_data ad;
+
+       rc = security_kdbus_sid(name, &name_sid);
+       if (rc)
+               return rc;
+
+       ad.type = LSM_AUDIT_DATA_KDBUS;
+       ad.u.kdbus_name = name;
+
+       return avc_has_perm(cred_sid(creds), name_sid,
+                           SECCLASS_KDBUS, KDBUS__SEE_NAME, &ad);
+}
+
+static int selinux_kdbus_conn_see_notification(const struct cred *creds)
+{
+       return avc_has_perm(SECINITSID_KERNEL, cred_sid(creds),
+                           SECCLASS_KDBUS, KDBUS__SEE_NOTIFICATION, NULL);
+}
+
+static int selinux_kdbus_proc_permission(const struct cred *creds,
+                                        struct pid *pid)
+{
+       int rc;
+       struct task_struct *task;
+
+       rcu_read_lock();
+       task = pid_task(pid, PIDTYPE_PID);
+       rc = avc_has_perm(cred_sid(creds), task_sid(task),
+                         SECCLASS_PROCESS, PROCESS__GETATTR, NULL);
+       rcu_read_unlock();
+
+       return rc;
+}
+
+static int selinux_kdbus_init_inode(struct inode *inode,
+                                   const struct cred *creds)
+{
+       struct inode_security_struct *isec = inode->i_security;
+       u32 sid = cred_sid(creds);
+
+       /* XXX - this is very simple, e.g. no transitions, no special object
+        *       class, etc. since this inode is basically an IPC socket ...
+        *       however, is this too simple?  do we want transitions?  if we
+        *       do, we should do the transition in kdbus_node_init() and not
+        *       here so that endpoint is labeled correctly and not just this
+        *       inode */
+
+       isec->inode = inode;
+       isec->task_sid = sid;
+       isec->sid = sid;
+       isec->sclass = SECCLASS_FILE;
+       isec->initialized = 1;
+
+       return 0;
+}
+
 static int selinux_ptrace_access_check(struct task_struct *child,
                                     unsigned int mode)
 {
@@ -5862,6 +6001,16 @@ static struct security_hook_list selinux_hooks[] = {
        LSM_HOOK_INIT(binder_transfer_binder, selinux_binder_transfer_binder),
        LSM_HOOK_INIT(binder_transfer_file, selinux_binder_transfer_file),
 
+       LSM_HOOK_INIT(kdbus_conn_new, selinux_kdbus_conn_new),
+       LSM_HOOK_INIT(kdbus_own_name, selinux_kdbus_own_name),
+       LSM_HOOK_INIT(kdbus_conn_talk, selinux_kdbus_conn_talk),
+       LSM_HOOK_INIT(kdbus_conn_see_name, selinux_kdbus_conn_see_name),
+       LSM_HOOK_INIT(kdbus_conn_see, selinux_kdbus_conn_see),
+       LSM_HOOK_INIT(kdbus_conn_see_notification,
+                     selinux_kdbus_conn_see_notification),
+       LSM_HOOK_INIT(kdbus_proc_permission, selinux_kdbus_proc_permission),
+       LSM_HOOK_INIT(kdbus_init_inode, selinux_kdbus_init_inode),
+
        LSM_HOOK_INIT(ptrace_access_check, selinux_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, selinux_ptrace_traceme),
        LSM_HOOK_INIT(capget, selinux_capget),
diff --git a/security/selinux/include/classmap.h 
b/security/selinux/include/classmap.h
index 5a4eef5..95eb6c3 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -157,5 +157,9 @@ struct security_class_mapping secclass_map[] = {
          { COMMON_SOCK_PERMS, "attach_queue", NULL } },
        { "binder", { "impersonate", "call", "set_context_mgr", "transfer",
                      NULL } },
+       { "kdbus", { "impersonate", "fakecreds", "fakepids", "owner",
+                    "privileged", "activator", "monitor", "policy_holder",
+                    "connect", "own", "talk", "see", "see_name",
+                    "see_notification", NULL } },
        { NULL }
   };

--
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to