[PATCH] Enhanced Trusted Path Execution (TPE) Linux Security Module

Lorenzo Hernández García-Hierro
2005-01-06T02:53:18Z

[-- Attachment #1.1: Type: text/plain, Size: 2439 bytes --]

Hi,
This patch adds support for an enhanced Trusted Path Execution (TPE)
subsystem relying in the Linux Security Modules framework.
It's a rewrite of the IBM's TPE LSM module by Niki A. Rahimi, which adds
a couple of improvements and feature enhancements.

The most notable of them are support for per-gid basis access control
lists in runtime and kernel-configuration time (adds support for trusted
and untrusted user groups), procfs interface for statistics and runtime
information and debugging capabilities (for limiting the garbage
messages).

Also, the documentation has been rewritten and under the "Trusted Path
Execution (EXPERIMENTAL)" configuration option, has been added a "GID
for trusted users" key to make possible to set a default gid for a
specific trusted user group.

The reasons that give sense for including this, are that standard
Vanilla kernels have SELinux and LSM (SELinux already supports TPE
functionalities), but SELinux has less possibilities of being used by
those desktop or just not experienced users who are not already using
their distribution-specific SELinux implementation, even if they want
simple protections for their every-day system use, also, the
availability of some patch-sets with security enhancements (like
grsecurity) distracts users of being using the LSM framework or even
SELinux itself, in addition, this TPE has more features than
grsecurity's one in terms of per-users and groups acl basis, which make
easy the management of the TPE protection.
In short, after a first review you can see that it could worthy to
include this in the kernel sources.

Note: the code, as it is right now, has some limitations that would be
solved in a relatively short time manner, more short if more people
contribute to it.

The limitations of the current code are described
in ./Documentation/tpe-lsm.txt

Patch against 2.6.10 attached.
(not inside msg body for preventing messing up by archives-managing
software)

I will make available an independent-packaged version ASAP, which could
be built outside the kernel sources, at http://selinux.tuxedo-es.org

Cheers,
PS: I would appreciate to be CC'ed, as I'm not subscribed to the list.
(Just for mail traffic volume reasons, which i don't have time to
handle)
--
Lorenzo Hernández García-Hierro <lorenzo@gnu.org> [1024D/6F2B2DEC]
[2048g/9AE91A22] Hardened Debian head developer & project manager

[-- Attachment #1.2: tpe-20050106.diff --]
[-- Type: text/x-patch, Size: 35126 bytes --]

diff -Nur ../linux-2.6.10/Documentation/tpe-lsm.txt linux-2.6.10-tpe/Documentation/tpe-lsm.txt
--- ../linux-2.6.10/Documentation/tpe-lsm.txt 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-tpe/Documentation/tpe-lsm.txt 2005-01-06 02:52:34.000000000 +0100
@@ -0,0 +1,89 @@
+Trusted Path Execution Linux Security Module
+Copyright (C) 2003 IBM Corp. <narahimi@us.ibm.com>
+Copyright (C) 2005 Lorenzo Hernandez Garcia-Hierro <lorenzo@gnu.org>
+Author: Lorenzo HernÃ¡ndez Garcia-Hierro (Original: Niki Rahimi)
+This file is distributed according to the GNU General Public License.
+This module was tested on the Linux kernel 2.6.9 and 2.6.10.
+
+The purpose of the Trusted Path Execution Linux Security Module is to enable a
+check in the Linux kernel to limit the running of executables in trusted paths
+so that the potential for malicious code to be run on the system is reduced.
+A trusted path is one in which the parent directory of a file is owned by root
+and is neither group nor other writeable.
+The module relies on a kernel hook which checks to see if the given path is
+trusted or not and who is the user (or group member) that caused the event (execution).
+This check takes place directly upon an attempt to execute the code by using the
+bprm_set_security hook.
+
+Limitations: Right now, the engine does not use the bprm_secureexec hook to
+prevent use of sensitive LD_* variables by untrusted users or groups, also it
+does not use mmap nor mprotect LSM hooks that could prevent bypass of the
+bprm_set_security checks, as commented by Stephen S. Smalley <sds@epoch.ncsc.mil>.
+This features would be developed ASAP, but it's not a critical, blocking issue.
+
+The module also creates two Trusted Path access control lists which can be accessed
+by a sysfs mountpoint, inside the ./tpefs/ subdir (ie: /sys/tpefs), writeable by root,
+who can add and delete uids (user id's) and a entire range of users using the (new) native
+support for per-gid (group id) basis access control lists. A user on the list is
+considered trusted.
+Also, it creates a procfs entry called "tpe" (ie: /proc/tpe) which provides
+version information, total amount of trusted users, total amount of trusted groups and
+other information, depending on the code revision), and those who want extra garbage
+from the kernel will like to enabled debugging by passing debug=1 to the module parameters.
+By default, root is hard coded onto this list with also a trusted gid
+which gets automatically added when selecting the "GID for trusted users" option in kernel
+configuration (SECURITY_TPE_TRUSTED_GID).
+
+Thus if user A attempts to run an executable in path A, the following scenarios
+can play out:
+
+1. Trusted user,trusted path = User is able to run the executable.
+2. Trusted user,trusted path,trusted group = User is able to run the executable.
+3. Trusted user,untrusted path = User is able to run the executable.
+4. Trusted user,untrusted path,trusted group = User is able to run the executable.
+5. Trusted user,untrusted path,untrusted group = User is able to run the executable.
+6. Untrusted user,trusted path = User is able to run the executable.
+7. Untrusted user,trusted path,trusted group = User is able to run the executable.
+8. Untrusted user,trusted path,untrusted group = User is able to run the executable.
+9. Untrusted user,untrusted path = User is not able to run the executable.#
+10. Untrusted user,untrusted path,trusted group = User is able to run the executable.
+11. Untrusted user,untrusted path,untrusted group= User is not able to run the executable.#
+
+In short, if the path and user are both untrusted (and also if the group
+is untrusted), execution will be denied sending a message with the uid,gid,
+euid,egid,pid and binary that caused the event.
+
+In order to actually modify the access control list for TPE, the module uses
+a sysfs subsystem called tpefs. The tpefs contains four files; add, del, add-group
+and del-group.
+Performing read and write operations on the aforementioned files creates a user
+to system interface that will alter the TPE access control list. See
+"Modifying the TPE Access Control Lists" below for the methods of altering the list
+using these files.
+Note: The original two file approach was utilized rather than a single file in order to
+keep the code and administration of the module simple for both the kernel and
+the user, and it was when only uid-based access control lists were supported, now
+i've followed the same style to provide backwards compatibility.
+
+Installation:
+1. Recompile the kernel to include LSM and TPE as a module (or even get a
+ kernel-independent packaged TPE module.
+2. mount -t sysfs sysfs <mountpoint>
+3. modprobe tpe debug=1/0 (if you want to use debugging set to 1)
+4. See "Modifying the TPE Access Control Lists" below for instructions on how to
+add/delete users and groups to/from the list.
+
+Modifying the TPE Access Control Lists:
+
+- Adding a user : echo <uid> > <mountpoint>/tpefs/add
+- Deleting a user : echo <uid> > <mountpoint>/tpefs/del
+- Adding a group : echo <gid> > <mountpoint>/tpefs/add-group
+- Deleting a group : echo <gid> > <mountpoint>/tpefs/del-group
+- Show uid list to userspace: cat <mountpoint>/tpefs/add
+- Show gid list to userspace: cat <mountpoint>/tpefs/add-group
+- Show version and statistics information: cat /proc/tpe
+
+Note: Advanced users would be interested in writing a script or something
+to modify the access control lists in a fine-grained manner, but this is out
+of the goals of the TPE development, anyway, feel free to send your contributions
+to lorenzo@gnu.org.
diff -Nur ../linux-2.6.10/security/Kconfig linux-2.6.10-tpe/security/Kconfig
--- ../linux-2.6.10/security/Kconfig 2005-01-03 19:43:05.000000000 +0100
+++ linux-2.6.10-tpe/security/Kconfig 2005-01-06 03:45:09.115252528 +0100
@@ -84,6 +84,37 @@

If you are unsure how to answer this question, answer N.

+config SECURITY_TPE
+ tristate "Trusted Path Execution (EXPERIMENTAL)"
+ depends on SECURITY && EXPERIMENTAL
+ help
+ The TPE module enforces a check on the running of executables.
+ It will not allow execution if the program is located in a
+ "trusted path" and the current user is "untrusted". A trusted
+ path is one which is root owned and neither group nor other
+ writeable. An user is considered trusted if their uid is added
+ to a trusted list in memory, also, user groups can be trusted
+ in kernel compile-time and runtime by adding them to the gid-basis
+ access control list.Root is trusted, by default.A proc interface
+ /proc/tpe is created when module loads, it shows version and ACL
+ information to use third-party checkers or scripts.
+ Original code for 2.5.59 by Niki A. Rahimi <narahimi@us.ibm.com>.
+
+ (c) 2005, Lorenzo Hernandez Garcia-Hierro <lorenzo@gnu.org>.
+
+ Read ./Documentation/tpe-lsm.txt for more information.
+ If you are unsure how to answer this question, answer N.
+
+config SECURITY_TPE_TRUSTED_GID
+ int "GID for trusted users"
+ depends on SECURITY_TPE
+ default 1337
+ help
+ Users with the primary group id given here will not be subject to the
+ trusted path restrictions by default. These users will therefore
+ represent a security risk to themselves and potentially to the system.
+ Please be sure that you can trust the members of this group.
+
source security/selinux/Kconfig

endmenu
diff -Nur ../linux-2.6.10/security/Makefile linux-2.6.10-tpe/security/Makefile
--- ../linux-2.6.10/security/Makefile 2005-01-03 19:43:05.000000000 +0100
+++ linux-2.6.10-tpe/security/Makefile 2005-01-04 02:10:45.000000000 +0100
@@ -17,3 +17,4 @@
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
obj-$(CONFIG_SECURITY_SECLVL) += seclvl.o
+obj-$(CONFIG_SECURITY_TPE) += tpe.o
diff -Nur ../linux-2.6.10/security/tpe.c linux-2.6.10-tpe/security/tpe.c
--- ../linux-2.6.10/security/tpe.c 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-tpe/security/tpe.c 2005-01-06 02:51:35.000000000 +0100
@@ -0,0 +1,624 @@
+/*
+ * Trusted Path Execution Security Module
+ *
+ * This module provides a Trusted Path Execution (TPE) engine to the
+ * Linux kernel. TPE originated as a kernel patch to OpenBSD 2.4 by
+ * route|daemon9 and Mike Schifman (see Phrack 54). IBM originally modified
+ * the original project to fit within the constraints of the LSM framework
+ * and so it should be noted that this is not the same project. Also,
+ * the module makes use of the sysfs filesystem.
+ * I rewrote the module in order to add debugging, better information
+ * outputting, support for per-User-Groups access control lists at runtime
+ * and kernel-configuration level, a procfs interface for general information
+ * gathering from the TPE subsystem and a few other enhancements which make the
+ * code almost a complete rewrite.
+ *
+ * Copyright (C) 1998 route|daemon9 and Mike D. Schiffman
+ * Copyright (C) 2001-2002 Greg Kroah-Hartman <gregkh@us.ibm.com>
+ * Copyright (C) 2003 IBM Corp. <narahimi@us.ibm.com>
+ * Copyright (C) 2005 Lorenzo Hernandez Garcia-Hierro <lorenzo@gnu.org>
+ * All rights reversed.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/security.h>
+#include <linux/skbuff.h>
+#include <linux/netlink.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <asm/uaccess.h>
+#include <linux/pagemap.h>
+#include <linux/namei.h>
+#include <linux/vfs.h>
+#include <linux/mount.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/proc_fs.h>
+
+#include "tpe.h"
+
+static int secondary;
+static spinlock_t tpe_acl_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t tpe_group_acl_lock = SPIN_LOCK_UNLOCKED;
+
+/* debugging */
+static int debug = 0;
+
+/* get debug=1/0 param */
+module_param(debug, bool, 0600);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+#if defined(CONFIG_SECURITY_TPE_MODULE)
+#define MY_NAME THIS_MODULE->name
+#else
+#define MY_NAME "TPE"
+#define LEGACY_NAME "tpe"
+#endif
+
+/* Module information */
+#define DESCRIPTION "Trusted Path Execution LSM Implementation"
+#define AUTHOR "Lorenzo Hernandez Garcia-Hierro <lorenzo@gnu.org>"
+#define LICENSE "GPL"
+
+/* TPE /proc entry */
+struct proc_dir_entry *TPE_pentry;
+
+/* Outputting and debugging functions */
+/* Debug should be explicitly enabled (debug=1) to give output back from dbg() */
+#define dbg(fmt, arg...) \
+ do { \
+ if (1 && debug) { \
+ printk(KERN_DEBUG "%s: " fmt , MY_NAME, ## arg); \
+ } \
+ } while (0)
+
+/* KERN_INFO messages use kinfo() rather than printk() for better outputting layout */
+#define kinfo(fmt, arg...) \
+ do { \
+ if (1) { \
+ printk(KERN_INFO "%s: " fmt , MY_NAME, ## arg); \
+ } \
+ } while (0)
+
+
+/* Insertion sort the list. */
+static void tpe_sort (int low, int high) /* (list low element, list high element) */
+{
+ int i,j,n;
+ /* Standard insertion sort. */
+ for (i = low + 1; i <= high; i++) {
+ if (tpe_acl[i] < tpe_acl[low]) {
+ tpe_acl[low] ^= tpe_acl[i];
+ tpe_acl[i] ^= tpe_acl[low];
+ tpe_acl[low] ^= tpe_acl[i];
+ }
+ }
+ /* tpe_acl */
+ for (i = low + 2; i <= high; i++) {
+ j = i;
+ n = tpe_acl[i];
+ while (n < tpe_acl[j - 1]) {
+ tpe_acl[j] = tpe_acl[j - 1];
+ j--;
+ }
+ tpe_acl[j] = n;
+ }
+}
+static void tpe_group_sort (int low, int high) /* (list low element, list high element) */
+{
+ int i,j,n;
+ /* Standard insertion sort for tpe_group_acl. */
+ for (i = low + 1; i <= high; i++) {
+ if (tpe_group_acl[i] < tpe_group_acl[low]) {
+ tpe_group_acl[low] ^= tpe_group_acl[i];
+ tpe_group_acl[i] ^= tpe_group_acl[low];
+ tpe_group_acl[low] ^= tpe_group_acl[i];
+ }
+ }
+ /* tpe_group_acl */
+ for (i = low + 2; i <= high; i++) {
+ j = i;
+ n = tpe_group_acl[i];
+ while (n < tpe_group_acl[j - 1]) {
+ tpe_group_acl[j] = tpe_group_acl[j - 1];
+ j--;
+ }
+ tpe_group_acl[j] = n;
+ }
+}
+
+/* Attempt to add an UID candidate to the list. */
+static int tpe_add (uid_t add_candidate)
+{
+ int retval = -EINVAL;
+
+ /* Full list. */
+ if (tpe_acl_candidates == (TPE_ACL_SIZE - 2)) {
+ kinfo("Unable to add user %d. List is full.\n",
+ add_candidate);
+ goto out;
+ }
+
+ if (add_candidate == 0) {
+ kinfo("Invalid user id. Cannot add.\n");
+ goto out;
+ }
+
+ /* Don't add duplicates */
+ if ((tpe_search(add_candidate)) == NACK) {
+ /* Add to the end of the list, then sort. */
+ tpe_acl_candidates++;
+ tpe_acl[tpe_acl_candidates] = add_candidate;
+ tpe_acl[tpe_acl_candidates + 1] = '\0'; /* terminate array */
+ tpe_sort(0, tpe_acl_candidates);
+ kinfo("UID %d added as trusted to access control list\n",
+ add_candidate);
+ } else {
+ kinfo("Duplicate UID %d not added\n",
+ add_candidate);
+ goto out;
+ }
+ retval = 0;
+out:
+ return retval;
+}
+
+/* Attempt to add an GID candidate to the list. */
+static int tpe_group_add (gid_t add_candidate)
+{
+ int retval = -EINVAL;
+
+ /* Full list. */
+ if (tpe_acl_group_candidates == (TPE_ACL_SIZE - 2)) {
+ kinfo("Unable to add user %d. List is full.\n",
+ add_candidate);
+ goto out;
+ }
+
+ if (add_candidate == 0) {
+ kinfo("Invalid userid. Cannot add.\n");
+ goto out;
+ }
+
+ /* Don't add duplicates */
+ if ((tpe_search_group(add_candidate)) == NACK) {
+ /* Add to the end of the list, then sort. */
+ tpe_acl_group_candidates++;
+ tpe_group_acl[tpe_acl_group_candidates] = add_candidate;
+ tpe_group_acl[tpe_acl_group_candidates + 1] = '\0'; /* terminate array */
+ tpe_group_sort(0, tpe_acl_group_candidates);
+ kinfo("GID %d added as trusted to access control list\n",
+ add_candidate);
+ } else {
+ kinfo("Duplicate GID %d not added\n",
+ add_candidate);
+ goto out;
+ }
+ retval = 0;
+out:
+ return retval;
+}
+
+/* Attempt to remove a candidate from the list. Only fails if the entry is */
+/* not there. */
+static int tpe_remove (uid_t rem_candidate)
+{
+ int n;
+ int retval = -EINVAL;
+ if (tpe_acl_candidates == 0) {
+ /* Empty list */
+ goto out;
+ }
+ if (rem_candidate == 0) {
+ kinfo("Invalid userid. Cannot remove.\n");
+ goto out;
+ }
+
+ n = tpe_search(rem_candidate);
+ if (n != NACK) {
+ /* Remove candidate (mark slot as unused), resort the list. */
+ tpe_acl[n] = TPE_INITIALIZER;
+ tpe_acl_candidates--;
+ tpe_sort(0, tpe_acl_candidates);
+ kinfo("UID %d removed from trust list\n",
+ rem_candidate);
+ retval = 0;
+ goto out;
+ }
+ /* Not found. */
+ kinfo("UID %d not found in trust list\n",
+ rem_candidate);
+out:
+ return retval;
+}
+
+/* GID removing */
+static int tpe_group_remove (gid_t rem_candidate)
+{
+ int n;
+ int retval = -EINVAL;
+ if (tpe_acl_group_candidates == 0) {
+ /* Empty groups list */
+ goto out;
+ }
+ if (rem_candidate == 0) {
+ kinfo("Invalid GID. Cannot remove.\n");
+ goto out;
+ }
+
+ n = tpe_search_group(rem_candidate);
+ if (n != NACK) {
+ /* Remove candidate (mark slot as unused), resort the list. */
+ tpe_group_acl[n] = TPE_INITIALIZER;
+ tpe_acl_group_candidates--;
+ tpe_group_sort(0, tpe_acl_group_candidates);
+ kinfo("GID %d removed from trust list\n",
+ rem_candidate);
+ retval = 0;
+ goto out;
+ }
+ /* Not found. */
+ kinfo("GID %d not found in trust list\n",
+ rem_candidate);
+out:
+ return retval;
+}
+
+
+/* Beginning of a sysfs subsystem for tpe */
+static struct subsystem tpefs_subsys;
+
+struct tpe_list {
+ char *name;
+
+ struct list_head slot_list;
+ struct kobject kobj;
+};
+
+struct tpefs_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct tpe_list *, char *);
+ ssize_t (*store)(struct tpe_list *, const char *, size_t);
+};
+
+static ssize_t tpefs_attr_show(struct kobject *kobj, struct attribute *attr,
+char *buf)
+{
+ struct tpe_list *list = container_of(kobj, struct tpe_list, kobj);
+ struct tpefs_attribute *attribute = container_of(attr, struct
+ tpefs_attribute, attr);
+ return attribute->show ? attribute->show(list, buf) : 0;
+}
+
+static ssize_t tpefs_attr_store(struct kobject *kobj, struct attribute *attr,
+const char *buf, size_t len)
+{
+ struct tpe_list *list = container_of(kobj, struct tpe_list, kobj);
+ struct tpefs_attribute *attribute = container_of(attr, struct
+ tpefs_attribute, attr);
+ return attribute->store ? attribute->store(list, buf, len) : 0;
+}
+
+static struct sysfs_ops tpefs_sysfs_ops = {
+ .show = tpefs_attr_show,
+ .store = tpefs_attr_store,
+};
+
+static struct kobj_type tpefs_ktype = {
+ .sysfs_ops = &tpefs_sysfs_ops
+};
+
+static decl_subsys(tpefs, &tpefs_ktype, NULL);
+
+static ssize_t trustedlistadd_read_file (struct tpe_list *list, char *buf)
+{
+ int i;
+ int retval = 0;
+ char *user = NULL;
+ char buffer[400];
+
+ user = (char *)__get_free_page(GFP_KERNEL);
+ if (!user)
+ return -ENOMEM;
+
+ if (tpe_acl == NULL) {
+ kinfo("Empty Access Control List\n");
+ return -ENODATA;
+ }
+
+ buffer[0] = '\0';
+ kinfo("%d trusted user(s): \n", tpe_acl_candidates);
+ spin_lock(&tpe_acl_lock);
+ for (i=0; i < tpe_acl_candidates; i++) {
+ printk(KERN_INFO "%d ", tpe_acl[i]);
+ retval = sprintf(user, "%d\n", tpe_acl[i]);
+ strcat(buffer, user);
+ }
+ /* leave printk() calls alone, not kinfo() */
+ printk(KERN_INFO "\n");
+ spin_unlock(&tpe_acl_lock);
+
+ retval = snprintf(buf, 4096, "%s\n", buffer);
+
+ free_page((unsigned long)user);
+ return retval;
+}
+
+static ssize_t trustedlistadd_write_file (struct tpe_list *list, const char *buf,
+size_t count)
+{
+ int retval;
+ unsigned long add_candidate;
+
+ add_candidate = simple_strtoul(buf, NULL, 10);
+
+ dbg("value of add_candidate is %d.\n", (int)add_candidate);
+ spin_lock(&tpe_acl_lock);
+ retval = tpe_add(add_candidate);
+ spin_unlock(&tpe_acl_lock);
+ if (retval) {
+ return retval;
+ }
+ return count;
+
+}
+
+/* per-GID basis ACL support */
+
+static ssize_t trustedlistadd_group_write_file (struct tpe_list *list, const char *buf,
+size_t count)
+{
+ int retval;
+ unsigned long add_group_candidate;
+
+ add_group_candidate = simple_strtoul(buf, NULL, 10);
+
+ dbg("value of add_group_candidate is %d.\n", (int)add_group_candidate);
+ spin_lock(&tpe_group_acl_lock);
+ retval = tpe_group_add(add_group_candidate); /* tpe_group_add() ninja monkey */
+ spin_unlock(&tpe_group_acl_lock);
+ if (retval) {
+ return retval;
+ }
+ return count;
+
+}
+static ssize_t trustedlistadd_group_read_file (struct tpe_list *list, char *buf)
+{
+ int i;
+ int retval = 0;
+ char *group = NULL;
+ char buffer[400];
+
+ group = (char *)__get_free_page(GFP_KERNEL);
+ if (!group)
+ return -ENOMEM;
+
+ if (tpe_acl == NULL) {
+ kinfo("Empty user groups Access Control List\n");
+ return -ENODATA;
+ }
+
+ buffer[0] = '\0';
+ kinfo("%d trusted group(s): \n", tpe_acl_group_candidates);
+ spin_lock(&tpe_group_acl_lock);
+ for (i=0; i < tpe_acl_group_candidates; i++) {
+ printk(KERN_INFO "%d ", tpe_group_acl[i]);
+ retval = sprintf(group, "%d\n", tpe_group_acl[i]);
+ strcat(buffer, group);
+ }
+ /* leave printk() calls alone, not kinfo() */
+ printk(KERN_INFO "\n");
+ spin_unlock(&tpe_group_acl_lock);
+
+ retval = snprintf(buf, 4096, "%s\n", buffer);
+
+ free_page((unsigned long)group);
+ return retval;
+}
+/* ends sysfs tpefs group acl management */
+
+struct tpefs_attribute tpefs_listadd_attr = {
+ .attr = {.name = "add", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = trustedlistadd_read_file,
+ .store = trustedlistadd_write_file
+};
+/* listadd_group per-GID basis ACL */
+struct tpefs_attribute tpefs_listadd_group_attr = {
+ .attr = {.name = "add-group", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .show = trustedlistadd_group_read_file,
+ .store = trustedlistadd_group_write_file
+};
+/* trusted UIDs deletion */
+static ssize_t trustedlistdel_write_file (struct tpe_list *list, const char *buf,
+size_t count)
+{
+ int retval;
+ unsigned long rem_candidate;
+
+ rem_candidate = simple_strtoul(buf, NULL, 10);
+
+ dbg("value of rem_candidate is %d.\n", (int)rem_candidate);
+ spin_lock(&tpe_acl_lock);
+ retval = tpe_remove(rem_candidate);
+ spin_unlock(&tpe_acl_lock);
+ if (retval) {
+ return retval;
+ }
+ return count;
+
+}
+/* trusted GIDs deletion */
+static ssize_t trustedlistdel_group_write_file (struct tpe_list *list, const char *buf,
+size_t count)
+{
+ int retval;
+ unsigned long rem_group_candidate;
+
+ rem_group_candidate = simple_strtoul(buf, NULL, 10);
+
+ dbg("value of rem_candidate is %d.\n", (int)rem_group_candidate);
+ spin_lock(&tpe_group_acl_lock);
+ retval = tpe_group_remove(rem_group_candidate);
+ spin_unlock(&tpe_group_acl_lock);
+ if (retval) {
+ return retval;
+ }
+ return count;
+
+}
+
+struct tpefs_attribute tpefs_listdel_attr = {
+ .attr = {.name = "del", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .store = trustedlistdel_write_file
+};
+/* sysfs/tpefs/del-group */
+struct tpefs_attribute tpefs_listdel_group_attr = {
+ .attr = {.name = "del-group", .mode = S_IFREG | S_IRUGO | S_IWUSR},
+ .store = trustedlistdel_group_write_file
+};
+
+/* TPE /proc entry managing */
+ssize_t
+procfile_read(char *buffer,
+ char **buffer_location,
+ off_t offset, int buffer_length, int *eof, void *data)
+{
+ int len = 0; /* The number of bytes actually used */
+ char *vermagic = VERSION;
+ if (offset > 0) {
+ dbg("offset %d : /proc/tpe : procfile_read, \
+ wrote %d bytes\n", (int)(offset), len);
+ *eof = 1;
+ return len;
+ }
+ /* We write the data to the procfs entry */
+ len = sprintf(buffer,
+ "Version: %s\nTrusted users: %d\nTrusted groups: %d\n"
+ , vermagic, tpe_acl_candidates, tpe_acl_group_candidates);
+ /* Voila! */
+ dbg("leaving /proc/tpe : procfile_read, wrote %d Bytes\n", len);
+ return len;
+}
+
+/* Module code */
+
+static int tpe_bprm_set_security (struct linux_binprm *bprm)
+{
+ uid_t pthuid = bprm->file->f_dentry->d_parent->d_inode->i_uid;
+ mode_t pthmode = bprm->file->f_dentry->d_parent->d_inode->i_mode;
+ if((!TRUSTED_PATH(pthmode, pthuid)) && (!TRUSTED_USER(current->euid))
+ && (!TRUSTED_GROUP(bprm->e_gid))) {
+ kinfo("Untrusted execution: %s "
+ "uid/euid=%d/%d gid/egid=%d/%d pid=%d"
+ "\n", bprm->filename, current->uid, bprm->e_uid,
+ current->gid, bprm->e_gid, current->pid);
+ return -EACCES;
+ }
+ return 0;
+}
+
+struct security_operations tpe_security_ops = {
+ bprm_set_security: tpe_bprm_set_security,
+};
+
+static int __init tpe_module_init (void)
+{
+ int retval;
+ int cfoo = 0;
+ /* register ourselves with the security framework */
+ if (register_security (&tpe_security_ops)) {
+ printk (KERN_INFO
+ "Failure registering tpe module with the kernel\n");
+ /* try registering with primary module */
+ if (mod_reg_security (LEGACY_NAME, &tpe_security_ops)) {
+ printk (KERN_INFO "Failure registering tpe module "
+ "with primary security module.\n");
+ return -EINVAL;
+ }
+ secondary = 1;
+ }
+
+ /* register tpe subsystem */
+ kinfo("Registering TPE subsystem.\n");
+ retval = subsystem_register(&tpefs_subsys);
+ if (retval) {
+ kinfo("subsystem_register failed with %d\n", retval);
+ return retval;
+ }
+ kinfo("Registering tpefs support for sysfs.\n");
+ sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_attr.attr);
+ sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_attr.attr);
+ /* create the group/gid acl sysfs tpefs files */
+ sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_group_attr.attr);
+ sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_group_attr.attr);
+
+ kinfo("Registering with LSM subsystem.\n");
+ tpe_init();
+ /* TPE /proc/ "bilbo" entry begins :) */
+ TPE_pentry = create_proc_entry(TPE_PROC_ENTRY_NAME, 0644, NULL);
+ TPE_pentry->read_proc = procfile_read;
+ TPE_pentry->owner = THIS_MODULE;
+ TPE_pentry->mode = S_IFREG | S_IRUGO;
+ TPE_pentry->uid = 0;
+ TPE_pentry->gid = 0;
+ TPE_pentry->size = 20;
+ if (TPE_pentry == NULL) {
+ cfoo = -ENOMEM; /**/
+ remove_proc_entry(TPE_PROC_ENTRY_NAME, &proc_root);
+ kinfo("Error: Could not initialize /proc/tpe\n");
+ } else {
+ kinfo("/proc entry initialized.\n");
+ }
+ kinfo("Trusted Path Execution engine initialized.\n");
+ return cfoo;
+}
+
+static void __exit tpe_exit (void)
+{
+ remove_proc_entry(TPE_PROC_ENTRY_NAME, &proc_root); /* remove TPE /proc entry */
+ sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_attr.attr);
+ sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_attr.attr);
+ /* remove sysfs/tpefs/add-group and del-group */
+ sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_group_attr.attr);
+ sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_group_attr.attr);
+ subsystem_unregister(&tpefs_subsys);
+
+ /* remove ourselves from the security framework */
+ if (secondary) {
+ if (mod_unreg_security (LEGACY_NAME, &tpe_security_ops))
+ printk (KERN_INFO "Failure unregistering tpe module "
+ "with primary module.\n");
+ return;
+ }
+
+ if (unregister_security (&tpe_security_ops)) {
+ printk (KERN_INFO
+ "Failure unregistering tpe module with the kernel\n");
+ }
+ kinfo("Trusted Path Execution subsystem unloaded.\n");
+
+}
+
+module_init (tpe_module_init);
+module_exit (tpe_exit);
+
+/* Modinfo perls */
+MODULE_DESCRIPTION(DESCRIPTION);
+MODULE_AUTHOR(AUTHOR);
+MODULE_LICENSE(LICENSE);
diff -Nur ../linux-2.6.10/security/tpe.h linux-2.6.10-tpe/security/tpe.h
--- ../linux-2.6.10/security/tpe.h 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.10-tpe/security/tpe.h 2005-01-06 02:51:35.000000000 +0100
@@ -0,0 +1,155 @@
+/*
+ * Trusted Path Execution Security Module
+ *
+ * This module provides a Trusted Path Execution (TPE) engine to the
+ * Linux kernel. TPE originated as a kernel patch to OpenBSD 2.4 by
+ * route|daemon9 and Mike Schifman (see Phrack 54). IBM originally modified
+ * the original project to fit within the constraints of the LSM framework
+ * and so it should be noted that this is not the same project. Also,
+ * the module makes use of the sysfs filesystem.
+ * I rewrote the module in order to add debugging, better information
+ * outputting, support for per-User-Groups access control lists at runtime
+ * and kernel-configuration level, a procfs interface for general information
+ * gathering from the TPE subsystem and a few other enhancements which make the
+ * code almost a complete rewrite.
+ *
+ * Copyright (C) 2003 IBM Corp. <narahimi@us.ibm.com>
+ * Copyright (C) 2005 Lorenzo Hernandez Garcia-Hierro <lorenzo@gnu.org>
+ * All rights reversed.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __TPE_H
+#define __TPE_H
+
+#include <linux/types.h>
+#include <asm/uaccess.h>
+
+/* Vermagic and /proc entry name */
+
+#define VERSION "20050601"
+#define LSM_VERSION NULL /* unused */
+#define TPE_PROC_ENTRY_NAME "tpe" /* /proc entry name */
+
+/* Per-user group basis protection stuff */
+
+static int tpe_trusted_gid = 0;
+#ifdef CONFIG_SECURITY_TPE_TRUSTED_GID
+ tpe_trusted_gid = CONFIG_SECURITY_TPE_TRUSTED_GID;
+#endif
+/*
+ * syscall stuff
+ */
+#define TPE_ACL_SIZE 82 /* Maximum number of users in the list
+ * plus two. This was an original
+ * component of TPE. This will be
+ * fixed later on.
+ */
+
+#define TPE_INITIALIZER -1 /* A UID that isn't used */
+
+#define ACK 1 /* positive acknowledgement */
+#define NACK -1 /* negative acknowledgement */
+#define DUP 3 /* duplicate id return for tpe_add */
+
+/*
+ * Verify the path.
+ */
+#define TRUSTED_PATH(mode, uid) \
+(!(mode & (S_IWGRP | S_IWOTH)) && (uid == 0))
+
+static uid_t tpe_acl[TPE_ACL_SIZE]; /* trusted users list */
+static gid_t tpe_group_acl[TPE_ACL_SIZE]; /* trusted user groups list */
+static int tpe_acl_candidates; /* number of users on the list */
+static int tpe_acl_group_candidates; /* number of user groups on the list */
+
+/*
+ * Verify the user. This macro is passed the user's ID from the
+ * tpe_bprm_set_security hook.
+ */
+
+#define TRUSTED_USER(UID) (tpe_verify(UID) == ACK)
+
+/*
+ * Verify the user group. This macro is passed the user's group ID from the
+ * tpe_bprm_set_security hook.
+ */
+
+#define TRUSTED_GROUP(GID) (tpe_group_verify(GID) == ACK)
+
+/* Initialize the array with default values (TPE_INITIALIZER). */
+
+/* Debugging and outputting functions */
+
+static inline void tpe_init (void)
+{
+ memset(tpe_acl, TPE_INITIALIZER, sizeof(uid_t) * TPE_ACL_SIZE);
+ printk(KERN_INFO "TPE: Access Control List created.\n");
+ tpe_acl_candidates = 1;
+ if (!(tpe_trusted_gid == 0))
+ {
+ tpe_acl_group_candidates = 2;
+ } else {
+ tpe_acl_group_candidates = 1;
+ }
+ tpe_acl[0] = 0;
+ if (!(tpe_trusted_gid == 0))
+ {
+ tpe_group_acl[0] = 0;
+
+ tpe_group_acl[1] = tpe_trusted_gid;
+ } else {
+ tpe_group_acl[0] = 0;
+ }
+}
+
+/* Locate a uid in the list */
+static inline int tpe_search (uid_t candidate)
+{
+ int i;
+ for (i = 0; i < tpe_acl_candidates; i++) {
+ if (candidate == tpe_acl[i]) {
+ return i;
+ }
+ }
+ return NACK;
+}
+
+/* Verify a candidate user. */
+static inline int tpe_verify (uid_t candidate)
+{
+ if ((tpe_search(candidate)) != NACK) {
+ return (ACK);
+ }
+ return (NACK);
+}
+
+/* Verify a candidate user group. */
+static inline int tpe_search_group (gid_t group_candidate)
+{
+ int i;
+ for (i = 0; i < tpe_acl_group_candidates; i++) {
+ if (group_candidate == tpe_group_acl[i]) {
+ return i;
+ }
+ }
+ return NACK;
+}
+static inline int tpe_group_verify (gid_t group_candidate)
+{
+ if ((tpe_search_group(group_candidate)) != NACK) {
+ return (ACK);
+ }
+ return (NACK);
+}
+
+#endif /* __TPE_H */