+ return current_has_perm(current, PROCESS__FORK);
+}
+
+/*
+ * detach and free the LSM part of a set of credentials
+ */
+static void selinux_cred_free(struct cred *cred)
+{
+ struct task_security_struct *tsec = cred->security;
+ cred->security = NULL;
+ kfree(tsec);
+}
+
+/*
+ * prepare a new set of credentials for modification
+ */
+static int selinux_cred_prepare(struct cred *new, const struct cred *old,
+ gfp_t gfp)
+{
+ const struct task_security_struct *old_tsec;
+ struct task_security_struct *tsec;
+
+ old_tsec = old->security;
+
+ tsec = kmemdup(old_tsec, sizeof(struct task_security_struct), gfp);
+ if (!tsec)
+ return -ENOMEM;
+
+ new->security = tsec;
+ return 0;
+}
+
+/*
+ * commit new credentials
+ */
+static void selinux_cred_commit(struct cred *new, const struct cred *old)
+{
+ secondary_ops->cred_commit(new, old);
+}
+
+/*
+ * set the security data for a kernel service
+ * - all the creation contexts are set to unlabelled
+ */
+static int selinux_kernel_act_as(struct cred *new, u32 secid)
+{
+ struct task_security_struct *tsec = new->security;
+ u32 sid = current_sid();
+ int ret;
+
+ ret = avc_has_perm(sid, secid,
+ SECCLASS_KERNEL_SERVICE,
+ KERNEL_SERVICE__USE_AS_OVERRIDE,
+ NULL);
+ if (ret == 0) {
+ tsec->sid = secid;
+ tsec->create_sid = 0;
+ tsec->keycreate_sid = 0;
+ tsec->sockcreate_sid = 0;
+ }
+ return ret;