I apologize. This is not reversed plus adds tpe.txt to Documentation directory. diff -Naur linux-2.6.8/Documentation/tpe.txt linux-2.6.8tpe/Documentation/tpe.txt --- linux-2.6.8/Documentation/tpe.txt 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.8tpe/Documentation/tpe.txt 2004-10-08 14:47:57.000000000 -0700 @@ -0,0 +1,52 @@ +Trusted Path Execution LSM +Copyright (C) 2003 IBM Corp. <narahimi@private> +Author: Niki A. Rahimi +This file is distributed according to the GNU General Public License. +This module was tested on the Linux kernel 2.5.59. + +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. This check takes place directly upon an attempt to execute the +code. +The module also creates a Trusted Path access control list and utilizes a +userspace tool to add or remove users to the list. A user on the list is +considered trusted. By default, root is hard coded onto this list. +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, untrusted path = User is able to run the executable. +3. Untrusted user, trusted path = User is able to run the executable. +4. Untrusted user, untrusted path = User is not able to run the executable. + +In short, if the path and user are both untrusted, execution will be denied. + +In order to actually modify the access control list for TPE, the module uses +a sysfs subsystem called tpefs. The tpefs contains two files; add and del +Performing read and write operations on the aforementioned files creates a user +to system interface that will alter the trusted list. See "Modifying the +Trusted List" below for the methods of altering the list using these files. +Note: The 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. + +Installation: +1. Recompile the kernel to include LSM and TPE as a module. +2. mount -t sysfs sysfs <mountpoint> +3. insmod tpe.o +4. See "Modifying the Trusted List" below for instructions on how to add/delete +users to/from the list. + +Modifying the Trusted List: +Adding a user: echo <uid> > <mountpoint>/tpefs/add +Deleting a user: echo <uid> > <mountpoint>/tpefs/del +Show list to userspace: cat <mountpoint>/tpefs/add + +Note: The above methods utilizing echo and cat are good examples of how to +alter the list. If the user is so interested, they may utilize other methods +of read/write on the files in order to perform similar actions on the list. +One example might be doing a "more <mountpoint>/tpefs/add" in order to show the list. diff -Naur linux-2.6.8/security/Kconfig linux-2.6.8tpe/security/Kconfig --- linux-2.6.8/security/Kconfig 2004-10-08 14:54:33.000000000 -0700 +++ linux-2.6.8tpe/security/Kconfig 2004-10-08 14:47:31.000000000 -0700 @@ -44,6 +44,20 @@ If you are unsure how to answer this question, answer N. +config SECURITY_TPE + tristate "Trusted Path Execution (EXPERIMENTAL)" + depends 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 an neither group nor other + writeable. A user is considered trusted if their uid is added + to a trusted list in memory. Root is trusted, by default. + Contact Niki A. Rahimi <narahimi@private> for more info. + + If you're unsure, answer N. + source security/selinux/Kconfig endmenu diff -Naur linux-2.6.8/security/Makefile linux-2.6.8tpe/security/Makefile --- linux-2.6.8/security/Makefile 2004-08-13 22:37:26.000000000 -0700 +++ linux-2.6.8tpe/security/Makefile 2004-10-08 14:47:36.000000000 -0700 @@ -14,4 +14,5 @@ # Must precede capability.o in order to stack properly. obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o +obj-$(CONFIG_SECURITY_TPE) += tpe.o obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o diff -Naur linux-2.6.8/security/tpe.c linux-2.6.8tpe/security/tpe.c --- linux-2.6.8/security/tpe.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.8tpe/security/tpe.c 2004-10-08 14:47:16.000000000 -0700 @@ -0,0 +1,375 @@ +/* + * Trusted Path Execution Security Module + * + * This module is an attempt to bring Trusted Path Execution (TPE) to the + * Linux kernel. TPE originated as a kernel patch to OpenBSD 2.4 by + * route|daemon9 and Mike Schifman (see Phrack 54). We have 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 a pseudo filesystem approach created by + * Greg Kroah-Hartman for his work on pcihotplug. + * + * Also, thanks and credit to Serge Hallyn for his help on getting the bugs + * out of this module. + * + * Copyright (C) 1998 route|daemon9 and Mike D. Schiffman + * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@private> + * Copyright (C) 2003 IBM Corp. <narahimi@private> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Alternatively, 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.* + */ + +#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 "tpe.h" + +static int secondary; +static spinlock_t tpe_acl_lock = SPIN_LOCK_UNLOCKED; + +/* 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]; + } + } + + 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; + } +} + +/* Attempt to add a 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)) { + printk(KERN_INFO "Unable to add user %d. List is full.\n", + add_candidate); + goto out; + } + + if (add_candidate == 0) { + printk(KERN_INFO "tpe: Invalid userid. 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); + printk(KERN_INFO "tpe: UID %d added to trust list\n", + add_candidate); + } else { + printk(KERN_INFO "tpe: duplicate UID %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) { + printk(KERN_INFO "tpe: 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); + printk(KERN_INFO "tpe: UID %d removed from trust list\n", + rem_candidate); + retval = 0; + goto out; + } + /* Not found. */ + printk(KERN_INFO "tpe: UID %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) { + printk(KERN_INFO "empty acl list\n"); + return -ENODATA; + } + + buffer[0] = '\0'; + printk(KERN_INFO "%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); + } + 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); + + printk(KERN_INFO "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; + +} + +struct tpefs_attribute tpefs_listadd_attr = { + .attr = {.name = "add", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .show = trustedlistadd_read_file, + .store = trustedlistadd_write_file +}; + +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); + + printk(KERN_INFO "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; + +} + +struct tpefs_attribute tpefs_listdel_attr = { + .attr = {.name = "del", .mode = S_IFREG | S_IRUGO | S_IWUSR}, + .store = trustedlistdel_write_file +}; + +/* 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))) { + printk (KERN_INFO "An attempt to run an executable " + "by an untrusted user was made in an untrusted " + "path. Access denied.\n"); + return -EACCES; + } + return 0; +} + +struct security_operations tpe_security_ops = { + bprm_set_security: tpe_bprm_set_security, +}; + +#if defined(CONFIG_SECURITY_TPE_MODULE) +#define MY_NAME THIS_MODULE->name +#else +#define MY_NAME "tpe" +#endif + +static int __init tpe_module_init (void) +{ + int retval; + /* 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 (MY_NAME, &tpe_security_ops)) { + printk (KERN_INFO "Failure registering tpe module " + "with primary security module.\n"); + return -EINVAL; + } + secondary = 1; + } + + /* register tpe subsystem */ + printk(KERN_INFO "registering tpe subsystem.\n"); + retval = subsystem_register(&tpefs_subsys); + if (retval) { + printk(KERN_INFO "subsystem_register failed with %d\n", retval); + return retval; + } + + sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_attr.attr); + sysfs_create_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_attr.attr); + + printk(KERN_INFO "tpe LSM initialized\n"); + tpe_init(); + printk(KERN_INFO "Trusted path execution initialized.\n"); + return 0; +} + +static void __exit tpe_exit (void) +{ + sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listadd_attr.attr); + sysfs_remove_file(&tpefs_subsys.kset.kobj, &tpefs_listdel_attr.attr); + subsystem_unregister(&tpefs_subsys); + + /* remove ourselves from the security framework */ + if (secondary) { + if (mod_unreg_security (MY_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"); + } + printk(KERN_INFO "tpe LSM removed\n"); + +} + +module_init (tpe_module_init); +module_exit (tpe_exit); + +MODULE_DESCRIPTION("LSM implementation of Trusted Path Execution"); +MODULE_LICENSE("Dual BSD/GPL"); diff -Naur linux-2.6.8/security/tpe.h linux-2.6.8tpe/security/tpe.h --- linux-2.6.8/security/tpe.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.8tpe/security/tpe.h 2004-10-08 14:47:22.000000000 -0700 @@ -0,0 +1,112 @@ +/* + * Trusted path ACL implementation created as a Loadable Security Module. + * This project is an abstraction of the original Trusted Path Execution + * patch to OpenBSD, which was created by route|daemon9 and Mike Schiffman. + * For the original OpenBSD write-up, see Phrack Magazine, issue 54, + * article 6 at http://www.phrack.com. + * + * A path is considered trusted if the parent directory is owned by root + * and is neither group nor world writeable. A user is considered trusted + * if she/he is on the kernels trust list, as created by this module. An + * untrusted user attempting to run an executable in an untrusted path + * will be denied execution. + * + * Copyright (c) 1998 route|daemon9 and Mike D. Schiffman + * Copyright (c) 2003 IBM Corp. <narahimi@private> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Alternatively, 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.* + */ + +#ifndef __TPE_H +#define __TPE_H + +#include <linux/types.h> +#include <asm/uaccess.h> + +/* + * 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 user list */ +static int tpe_acl_candidates; /* number of users 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) + +/* Initialize the array with default values (TPE_INITIALIZER). */ + +static inline void tpe_init (void) +{ + memset(tpe_acl, TPE_INITIALIZER, sizeof(uid_t) * TPE_ACL_SIZE); + printk(KERN_INFO "tpe_acl list created\n"); + tpe_acl_candidates = 1; + tpe_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); +} +#endif /* __TPE_H */
This archive was generated by hypermail 2.1.3 : Mon Oct 11 2004 - 11:36:59 PDT