Initial Import of Matthew Snelham <zeypher@sigalrm.com> Apparmor ebuilds

This commit is contained in:
geos_one 2006-08-13 22:35:00 +00:00
parent 2835e5b1d7
commit 57b6d1ece8
41 changed files with 15033 additions and 0 deletions

View File

@ -0,0 +1,10 @@
# ChangeLog for sec-policy/apparmor-profiles
# Copyright 1999-2006 Gentoo Foundation; Distributed under the GPL v2
# $Header: $
13 Aug 2006; Mario Fetka <mario-fetka@gmx.at>
+apparmor-profiles-2.0_p6376.ebuild:
Initial Import of
Matthew Snelham <zeypher@sigalrm.com>
Apparmor ebuilds

View File

@ -0,0 +1,8 @@
DIST apparmor-profiles-2.0-6376.tar.gz 33651 RMD160 cd64269b9c12fd60256f624b7b81aa1bddbb74c3 SHA1 151a18c3bc05355f24188cd1bc4b77cbae7e15dd SHA256 55103b0ce98616b6860fb43eff23587ad0faf5e38ab828bdd025d87a55b0f073
EBUILD apparmor-profiles-2.0_p6376.ebuild 1761 RMD160 c71682fbb885b3be54813c691258d4c6a3d6de59 SHA1 778fa06e704b167e03946a0a26f2b6e5f282f37f SHA256 350943388432d8280888d86ea36e3fb92af128c64553ef99f3421c07b2274d04
MD5 84869f70eb14cb24d0d296fa2f764cef apparmor-profiles-2.0_p6376.ebuild 1761
RMD160 c71682fbb885b3be54813c691258d4c6a3d6de59 apparmor-profiles-2.0_p6376.ebuild 1761
SHA256 350943388432d8280888d86ea36e3fb92af128c64553ef99f3421c07b2274d04 apparmor-profiles-2.0_p6376.ebuild 1761
MD5 45e145b77a88f384033973676b4cf1c0 files/digest-apparmor-profiles-2.0_p6376 277
RMD160 75b6c9ba5340bafa72a8410339ceeeda13a71d00 files/digest-apparmor-profiles-2.0_p6376 277
SHA256 b4229927d9665b3c60a9ba4d956d942083d5d7c59b8f3ced3c36d8741efad10d files/digest-apparmor-profiles-2.0_p6376 277

View File

@ -0,0 +1,58 @@
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
inherit eutils
MY_P="${P/_p/-}"
MY_S="${WORKDIR}/${P/_p*//}"
DESCRIPTION="AppArmor pre-built application encapsulation profiles."
HOMEPAGE="http://forge.novell.com/modules/xfmod/project/?apparmor"
SRC_URI="http://forge.novell.com/modules/xfcontent/private.php/apparmor/Development%20-%20April%20Snapshot/${MY_P}.tar.gz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~x86"
IUSE=""
DEPEND=""
RDEPEND=">=sys-apps/apparmor-2.0"
pkg_postinst() {
ewarn
ewarn "DO NOT EXPECT THESE PROFILES TO WORK ON YOUR SYSTEM!!!"
ewarn " Expect that ENABLING THEM WILL BREAK things"
ewarn " "
ewarn "These profiles were built to work with a SuSE base install, and "
ewarn "make many assumptions about file placement and system facilities "
ewarn "that are quite possibly untrue on any Gentoo system ever emerged."
ewarn " "
ewarn "They are provided for reference purposes only, until profiles can "
ewarn "be created and verified for Gentoo. If you are interested in using "
ewarn "AppArmor, and modifiying these base profiles for a Gentoo package, "
ewarn "please feel free to do so, and contact the AppArmor package "
ewarn "maintainer with your working profiles!"
ewarn
epause
}
src_unpack() {
unpack ${A}
cd ${MY_S}
# Move profiles to a different dir so that none of
# them are sourced by default on startup.
sed -i 's:apparmor.d$:apparmor.d/suse-defaults:g' Makefile
}
src_compile() {
cd ${MY_S}
emake CC="$(tc-getCC)" CFLAGS="${CFLAGS}" || die
}
src_install() {
cd ${MY_S}
# Place profiles in /usr/share, instead of /usr/src/Immunix
MY_SHAREDIR="/usr/share/${PN}"
make DESTDIR=${D} EXTRASDIR=${D}/${MY_SHAREDIR} install || die
}

View File

@ -0,0 +1,3 @@
MD5 526e971c18cc6588271e9ad1787adf2a apparmor-profiles-2.0-6376.tar.gz 33651
RMD160 cd64269b9c12fd60256f624b7b81aa1bddbb74c3 apparmor-profiles-2.0-6376.tar.gz 33651
SHA256 55103b0ce98616b6860fb43eff23587ad0faf5e38ab828bdd025d87a55b0f073 apparmor-profiles-2.0-6376.tar.gz 33651

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<herd>maintainer-wanted</herd>
</pkgmetadata>

View File

@ -0,0 +1,11 @@
# ChangeLog for sys-apps/apparmor
# Copyright 1999-2006 Gentoo Foundation; Distributed under the GPL v2
# $Header: $
13 Aug 2006; Mario Fetka <mario-fetka@gmx.at> +apparmor-2.0.ebuild, +TODO,
+files/aaeventd, +files/apparmor, +files/rc.apparmor.functions,
+files/rc.helper.functions:
Initial Import of
Matthew Snelham <zeypher@sigalrm.com>
AppArmor ebuilds

View File

@ -0,0 +1,30 @@
AUX aaeventd 824 RMD160 032cce20f81b7b0e1f6f38cb6e1c392d70407ad5 SHA1 8adaa5e21867cab21c5fa907c974fb94cb280f70 SHA256 dbaa7fd1197388146c7a1a9b59553815fdcd0498510f7b7bf752af88f8eb1780
MD5 379ee71ea946bd90c98e94e362bf9f2c files/aaeventd 824
RMD160 032cce20f81b7b0e1f6f38cb6e1c392d70407ad5 files/aaeventd 824
SHA256 dbaa7fd1197388146c7a1a9b59553815fdcd0498510f7b7bf752af88f8eb1780 files/aaeventd 824
AUX apparmor 1078 RMD160 cd1d37be5839e2b97973b6ee24c0d1d039a8210e SHA1 1a6b1ca658d7af1da895a5be6347c4ff8f18fee6 SHA256 f74877c1d728db4529e1d1bfacb16f3fba28b5a0b0ba8d8ab49d9cd3089204bd
MD5 c2d82bbd26c81516622a8e1142969b9a files/apparmor 1078
RMD160 cd1d37be5839e2b97973b6ee24c0d1d039a8210e files/apparmor 1078
SHA256 f74877c1d728db4529e1d1bfacb16f3fba28b5a0b0ba8d8ab49d9cd3089204bd files/apparmor 1078
AUX rc.apparmor.functions 11934 RMD160 42e76c294df2831deeb6037969e1373e8bc61a88 SHA1 eca09ad31c366dafe6291d2aceb4005bbbdc5374 SHA256 214eef64f76867295b446812df48faa90749d33a584e77070e2f84a576237519
MD5 5fab485513f92704bf834161f129018a files/rc.apparmor.functions 11934
RMD160 42e76c294df2831deeb6037969e1373e8bc61a88 files/rc.apparmor.functions 11934
SHA256 214eef64f76867295b446812df48faa90749d33a584e77070e2f84a576237519 files/rc.apparmor.functions 11934
AUX rc.helper.functions 546 RMD160 1a61b7d35491c8454fba1b5a892a37179e16b4fb SHA1 fda707b72b1498622b23aae0044abd9b7d0a9ab0 SHA256 6d58853c5945883a804e47b20e92369e106eb14390b6f8561cc5ccfe5418723e
MD5 91a6c3133fb4d0f7d35b5d25f587c01c files/rc.helper.functions 546
RMD160 1a61b7d35491c8454fba1b5a892a37179e16b4fb files/rc.helper.functions 546
SHA256 6d58853c5945883a804e47b20e92369e106eb14390b6f8561cc5ccfe5418723e files/rc.helper.functions 546
DIST apparmor-docs-2.0-6269.tar.gz 2697657 RMD160 474048d988d72cbf9bf21d50e8aef37d06d9b000 SHA1 792f4339d86d02d179b786de87a47394abfdadae SHA256 9c2d63bfe42cc4582e24d1248a7560dd19cee718db513c7dedb12d45fe168221
DIST apparmor-parser-2.0-25.tar.gz 154055 RMD160 371ed8a1c7b1ac2b7ee2e5add0225b709e7b9071 SHA1 aee31c18979d7ec8805c9f50300c7ed10b786e2d SHA256 fe83f57b8f588bad6de4527f375511b0d93b579dcd4f8bfb3d56c7e274782794
DIST apparmor-utils-2.0-6379.tar.gz 97162 RMD160 b4b3647a62d495e58cf476d6af1eaa7afc41daa5 SHA1 e1336bcecfffda464c8a1b8bd4883f4e52928cf5 SHA256 f4c819a36457f4ce53d50d3266f16b5801e5a5e583f18ad9df239e230d3a5465
EBUILD apparmor-2.0.ebuild 2557 RMD160 7df4146acdb534002908f38fdf18ce949f734be4 SHA1 4874525556509133fea655c5e18f1c35f3a582c0 SHA256 4bd511580c5467a237e2f5144f85aa1dd1f60c729645ed714b88ea6a1059577e
MD5 4e8616789c3911c43a4fc67fd281e902 apparmor-2.0.ebuild 2557
RMD160 7df4146acdb534002908f38fdf18ce949f734be4 apparmor-2.0.ebuild 2557
SHA256 4bd511580c5467a237e2f5144f85aa1dd1f60c729645ed714b88ea6a1059577e apparmor-2.0.ebuild 2557
MISC TODO 299 RMD160 07fdbfb908c9781718553cdf96b1f0a131540fef SHA1 33d47764bcf82c09f5aed67e3c38bbd5de0e6c18 SHA256 df384239f315f82c9c21b30bbd0e602007e7d3a251cba865738e8ef77951495f
MD5 a291d308d2e8c88e92cf1dc0b8b3ee2a TODO 299
RMD160 07fdbfb908c9781718553cdf96b1f0a131540fef TODO 299
SHA256 df384239f315f82c9c21b30bbd0e602007e7d3a251cba865738e8ef77951495f TODO 299
MD5 55d92fc75639f1bf39ae317b69b74048 files/digest-apparmor-2.0 807
RMD160 8e27a3a7d5ad23b2b516818272f9d89e8c120ad5 files/digest-apparmor-2.0 807
SHA256 0345343eced1c6ac9e5604e7c911eb72aeb02c2487084e267de66c7ac5ffc6ba files/digest-apparmor-2.0 807

View File

@ -0,0 +1,8 @@
Clean-up legacy code, where reasonable:
clean up init.d functions to enable Gentoo init conformance
## update rc.helper function defs for Gentoo
update rc.helper functions for other distros for push upstream
remove subdomain_parser man pages from doc section
Enable OWLSM submodule function

View File

@ -0,0 +1,118 @@
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
inherit eutils perl-module
PARSER_PN="apparmor-parser"
PARSER_PV="${PV}-25"
PARSER_P="${PARSER_PN}-${PARSER_PV}"
PARSER_S="${WORKDIR}/${PARSER_PN}-${PV}"
UTIL_PN="apparmor-utils"
UTIL_PV="${PV}-6379"
UTIL_P="${UTIL_PN}-${UTIL_PV}"
UTIL_S="${WORKDIR}/${UTIL_PN}-${PV}"
DOC_PN="apparmor-docs"
DOC_PV="${PV}-6269"
DOC_P="${DOC_PN}-${DOC_PV}"
DOC_S="${WORKDIR}/${DOC_PN}-${PV}"
DESCRIPTION="AppArmor provides easy to use application level security controls via the kernel Linux Security Modules interface."
HOMEPAGE="http://forge.novell.com/modules/xfmod/project/?apparmor"
SRC_URI="http://forge.novell.com/modules/xfcontent/private.php/${PN}/Development%20-%20April%20Snapshot/${PARSER_P}.tar.gz \
http://forge.novell.com/modules/xfcontent/private.php/${PN}/Development%20-%20April%20Snapshot/${UTIL_P}.tar.gz \
http://forge.novell.com/modules/xfcontent/private.php/apparmor/Development%20-%20April%20Snapshot/${DOC_P}.tar.gz"
LICENSE="GPL-2"
SLOT="0"
KEYWORDS="~x86"
IUSE=""
DEPEND="=sys-libs/libapparmor-2.0_p6288
sys-libs/libcap
dev-lang/perl
perl-core/Test-Harness
perl-core/Getopt-Long
dev-perl/DBI
dev-perl/DBD-SQLite
dev-perl/TimeDate
dev-perl/File-Tail
dev-perl/Locale-gettext
dev-libs/libpcre
sys-devel/bison
sys-devel/flex"
RDEPEND="sec-policy/apparmor-profiles"
# =sys-kernel/apparmor-sources-2.6.17
# ~sys-apps/apparmor-mod-2.0"
src_unpack() {
unpack ${A}
## apparmor-parser
cd ${PARSER_S}
# the Make.rules isn't needed for Gentoo
sed -i "s/^include Make.rules//g" Makefile
## apparmor-docs
cd ${DOC_S}
sed -i "s:NOVELL/SUSE:Gentoo:g" Makefile
}
src_compile() {
S_PKGS="${PARSE_S} ${UTIL_S} ${DOC_S}"
for pkg in ${S_PKGS}; do
cd ${pkg}
emake CC="$(tc-getCC)" CFLAGS="${CFLAGS}" || die
done
}
src_install() {
## apparmor-parser
cd ${PARSER_S}
make DESTDIR=${D} install || die
## apparmor-utils
cd ${UTIL_S}
perlinfo
make DESTDIR=${D} PERLDIR="${D}/${VENDOR_LIB}/Immunix" install || die
## apparmor-docs
cd ${DOC_S}
make DESTDIR=${D} install_manpages || die
# Some files are missing from the doc distribution, so no '|| die'
# bug submitted upstream
make DESTDIR=${D} DOCDIR=/usr/share/doc/${P} install_documents
## Init script and addtional files
doinitd ${FILESDIR}/apparmor
doinitd ${FILESDIR}/aaeventd
insopts -m0644
insinto /lib/apparmor
doins ${FILESDIR}/rc.helper.functions
doins ${FILESDIR}/rc.apparmor.functions
dodir /etc/apparmor.d/abstractions
}
pkg_postinst() {
ewarn
ewarn "TO USE APPARMOR YOU NEED AN APPARMOR AWARE KERNEL!!!"
ewarn " sys-kernel/apparmor-sources are apparmor aware"
# ewarn " "
# ewarn "These profiles were built to work with a SuSE base install, and "
# ewarn "make many assumptions about file placement and system facilities "
# ewarn "that are quite possibly untrue on any Gentoo system ever emerged."
# ewarn " "
# ewarn "They are provided for reference purposes only, until profiles can "
# ewarn "be created and verified for Gentoo. If you are interested in using "
# ewarn "AppArmor, and modifiying these base profiles for a Gentoo package, "
# ewarn "please feel free to do so, and contact the AppArmor package "
# ewarn "maintainer with your working profiles!"
# ewarn
epause
}

View File

@ -0,0 +1,40 @@
#!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
APPARMOR_HELPERS=/lib/apparmor/rc.helper.functions
if [ -f "${APPARMOR_HELPERS}" -a -f "${APPARMOR_FUNCTIONS}" ]; then
source ${APPARMOR_HELPERS}
source ${APPARMOR_FUNCTIONS}
else
eend 1 "Unable to find AppArmor initscript functions"
fi
depend() {
need apparmor
use logger dns
}
start() {
ebegin "Starting aaeventd (AppArmor Event Daemon)"
if [ "${APPARMOR_ENABLE_AAEVENTD}" = "no" ]; then
eend 1 " aaeventd disabled in ${APPARMOR_CONF}."
fi
start_sd_event
eend $waserror
}
stop() {
ebegin "Stopping aaeventd (AppArmor Event Daemon)"
stop_sd_event
eend $waserror
}
restart() {
srv_stop
srv_start
}

View File

@ -0,0 +1,56 @@
#!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
#
# rc.apparmor.gentoo by Matthew Snelham
#
# /etc/init.d/apparmor
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
APPARMOR_HELPERS=/lib/apparmor/rc.helper.functions
if [ -f "${APPARMOR_HELPERS}" -a -f "${APPARMOR_FUNCTIONS}" ]; then
source ${APPARMOR_HELPERS}
source ${APPARMOR_FUNCTIONS}
else
eend 1 "Unable to find AppArmor initscript functions"
fi
opts="${opts} reload status"
depend() {
need localmount
## AppArmor needs to be loaded before any other
## (potentially protected) user-space services come up.
#before *
}
start() {
ebegin "Starting AppArmor"
subdomain_start
einfo "...AppArmor Start"
eend $waserror
}
stop() {
ebegin "Stopping AppArmor"
subdomain_stop
einfo "...AppArmor Stop"
eend $waserror
}
restart() {
svc_stop; svc_start
}
reload() {
ebegin "Restarting AppArmor"
subdomain_restart
eend $?
}
status() {
ebegin "Checking AppArmor Status"
subdomain_status
eend $?
}

View File

@ -0,0 +1,9 @@
MD5 a5130a30a6a9e7cac316fe7658af031a apparmor-docs-2.0-6269.tar.gz 2697657
RMD160 474048d988d72cbf9bf21d50e8aef37d06d9b000 apparmor-docs-2.0-6269.tar.gz 2697657
SHA256 9c2d63bfe42cc4582e24d1248a7560dd19cee718db513c7dedb12d45fe168221 apparmor-docs-2.0-6269.tar.gz 2697657
MD5 1486ed6062435ff82340d6d9967b4df6 apparmor-parser-2.0-25.tar.gz 154055
RMD160 371ed8a1c7b1ac2b7ee2e5add0225b709e7b9071 apparmor-parser-2.0-25.tar.gz 154055
SHA256 fe83f57b8f588bad6de4527f375511b0d93b579dcd4f8bfb3d56c7e274782794 apparmor-parser-2.0-25.tar.gz 154055
MD5 0144c81537fd724eaa6e23822edaaae1 apparmor-utils-2.0-6379.tar.gz 97162
RMD160 b4b3647a62d495e58cf476d6af1eaa7afc41daa5 apparmor-utils-2.0-6379.tar.gz 97162
SHA256 f4c819a36457f4ce53d50d3266f16b5801e5a5e583f18ad9df239e230d3a5465 apparmor-utils-2.0-6379.tar.gz 97162

View File

@ -0,0 +1,443 @@
#!/bin/sh
#
# ----------------------------------------------------------------------
# Copyright (c) 1999, 2000, 20001, 2004, 2005, NOVELL (All rights reserved)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# 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.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, contact Novell, Inc.
# ----------------------------------------------------------------------
# rc.subdomain.functions by Steve Beattie
# Modified for Gentoo Linux, by Matthew Snelham
#
# Modifications Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
# NOTE: rc.subdomain initscripts that source this file need to implement
# the following set of functions:
# sd_action
# sd_log_info_msg
# sd_log_success_msg
# sd_log_warning_msg
# sd_log_failure_msg
CONFIG_DIR=/etc/apparmor
MODULE=apparmor
OLD_MODULE=subdomain
if [ -f "${CONFIG_DIR}/${MODULE}.conf" ] ; then
APPARMOR_CONF="${CONFIG_DIR}/${MODULE}.conf"
elif [ -f "${CONFIG_DIR}/${OLD_MODULE}.conf" ] ; then
APPARMOR_CONF="${CONFIG_DIR}/${OLD_MODULE}.conf"
else
sd_log_warning_msg "Unable to find config file in ${CONFIG_DIR}, installation problem?"
fi
# Read configuration options from ${APPARMOR_CONF}, default is to
# warn if subdomain won't load.
APPARMOR_MODULE_PANIC="warn"
SUBDOMAIN_ENABLE_OWLSM="no"
APPARMOR_ENABLE_AAEVENTD="no"
if [ -f "${APPARMOR_CONF}" ] ; then
source "${APPARMOR_CONF}"
fi
if [ -f /sbin/apparmor_parser ] ; then
PARSER=/sbin/apparmor_parser
else
sd_log_failure_msg "Unable to find apparmor_parser, installation problem?"
exit 1
fi
# APPARMOR_DIR might be redefined in ${APPARMOR_CONF}
if [ -d "${APPAMROR_DIR}" ] ; then
PROFILE_DIR=${APPARMOR_DIR}
elif [ -d /etc/apparmor.d ] ; then
PROFILE_DIR=/etc/apparmor.d
fi
ABSTRACTIONS="-I${PROFILE_DIR}"
AA_EV_BIN=/usr/sbin/aa-eventd
AA_EV_PIDFILE=/var/run/aa-eventd.pid
AA_STATUS=/usr/sbin/apparmor_status
SD_EV_BIN=/usr/sbin/sd-event-dispatch.pl
SD_EV_PIDFILE=/var/run/sd-event-dispatch.init.pid
SD_STATUS=/usr/sbin/subdomain_status
if grep -q securityfs /proc/filesystems ; then
SECURITYFS=/sys/kernel/security
fi
SUBDOMAINFS_MOUNTPOINT=$(grep subdomainfs /etc/fstab | \
sed -e 's|^[[:space:]]*[^[:space:]]\+[[:space:]]\+\(/[^[:space:]]*\)[[:space:]]\+subdomainfs.*$|\1|' 2> /dev/null)
if [ -d "/var/lib/${MODULE}" ] ; then
APPARMOR_TMPDIR="/var/lib/${MODULE}"
else
APPARMOR_TMPDIR="/tmp"
fi
function parse_profiles() {
# get parser arg
case "$1" in
load)
PARSER_ARGS="--add"
PARSER_MSG="Loading AppArmor profiles "
;;
reload)
PARSER_ARGS="--replace"
PARSER_MSG="Reloading AppArmor profiles "
;;
*)
exit 1
;;
esac
sd_log_info_msg "$PARSER_MSG"
# run the parser on all of the apparmor profiles
if [ ! -f "$PARSER" ]; then
sd_log_failure_msg "$PARSER_MSG - AppArmor parser not found"
exit 1
fi
if [ ! -d "$PROFILE_DIR" ]; then
sd_log_failure_msg "$PARSER_MSG - Profile directory not found"
exit 1
fi
if [ "X" == "X$(ls $PROFILE_DIR/)" ]; then
sd_log_warning_msg "$PARSER_MSG - No profiles found"
exit 1
fi
for profile in $PROFILE_DIR/*; do
if [ "${profile%.rpmnew}" != "${profile}" -o \
"${profile%.rpmsave}" != "${profile}" -o \
"${profile%\~}" != "${profile}" ]
then
sd_log_warning_msg "Skipping profile $profile"
elif [ -f "${profile}" ] ; then
sd_action " Adding profile: `basename ${profile}`" $PARSER $ABSTRACTIONS $PARSER_ARGS ${profile}
if [ $? -ne 0 ]; then
waserror=1
fi
fi
done
}
function profiles_names_list() {
# run the parser on all of the apparmor profiles
TMPFILE=$1
if [ ! -f "$PARSER" ]; then
sd_log_failure_msg "AppArmor parser ($PARSER) not found"
exit 1
fi
if [ ! -d "$PROFILE_DIR" ]; then
sd_log_failure_msg "Profile directory ($PROFILE_DIR) not found"
exit 1
fi
for profile in $PROFILE_DIR/*; do
if [ "${profile%.rpmnew}" != "${profile}" -o \
"${profile%.rpmsave}" != "${profile}" -o \
"${profile%\~}" != "${profile}" ]
then
echo "nop" >/dev/null
elif [ -f "${profile}" ] ; then
LIST_ADD=$($PARSER $ABSTRACTIONS -N "$profile" | grep -v '\^')
if [ $? -eq 0 ]; then
echo "$LIST_ADD" >>$TMPFILE
fi
fi
done
}
function is_securityfs_mounted() {
if grep -q securityfs /proc/filesystems && grep -q securityfs /proc/mounts ; then
if [ -f "${SECURITYFS}/${MODULE}/profiles" ]; then
SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}"
return 0
fi
fi
return 1
}
function mount_securityfs() {
if [ "X" != "X${SECURITYFS}" ]; then
if ! grep -q securityfs /proc/mounts ; then
sd_action "Mounting securityfs on ${SECURITYFS}" \
mount -t securityfs securityfs "${SECURITYFS}"
rc=$?
if [ -f "${SECURITYFS}/${MODULE}/profiles" ]; then
SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}"
else
SFS_MOUNTPOINT="${SECURITYFS}/${MODULE}"
fi
return $rc
fi
fi
return 0
}
function unmount_securityfs() {
SUBDOMAINFS=$(grep subdomainfs /proc/mounts | cut -d" " -f2 2> /dev/null)
if [ "X" != "X${SUBDOMAINFS}" ]; then
sd_action "Unmounting securityfs" umount ${SUBDOMAINFS}
fi
}
function failstop_system() {
level=$(runlevel | cut -d" " -f2)
if [ $level -ne "1" ] ; then
sd_log_failure_msg "Could not start AppArmor. Changing to runlevel 1"
telinit 1;
return -1;
fi
sd_log_failure_msg "Could not start AppArmor."
return -1
}
function module_panic() {
# the module failed to load, determine what action should be taken
case "$APPARMOR_MODULE_PANIC" in
"warn"|"WARN") sd_log_failure_msg "Could not start AppArmor"
return -1 ;;
"panic"|"PANIC") failstop_system
rc=$?
return $rc ;;
*) sd_log_failure_msg "Invalid AppArmor module fail option"
return -1 ;;
esac
}
function load_module() {
if modinfo -F filename apparmor > /dev/null 2>&1 ; then
MODULE=apparmor
elif modinfo -F filename subdomain > /dev/null 2>&1 ; then
MODULE=subdomain
fi
if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then
sd_action "Loading AppArmor module" /sbin/modprobe $MODULE $1
rc=$?
if [ $rc -ne 0 ] ; then
# we couldn't find the module
module_panic
rc=$?
if [ $rc -ne 0 ] ; then
exit $rc
fi
fi
fi
}
function start_sd_event() {
if [ -x "$AA_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
sd_action "Starting AppArmor Event daemon" startproc -f -p $AA_EV_PIDFILE $AA_EV_BIN -p $AA_EV_PIDFILE
elif [ -x "$SD_EV_BIN" -a "${APPARMOR_ENABLE_AAEVENTD}" = "yes" ] ; then
sd_action "Starting AppArmor Event daemon" startproc -f -p $SD_EV_PIDFILE $SD_EV_BIN -p $SD_EV_PIDFILE
fi
}
function stop_sd_event() {
if [ -x "$AA_EV_BIN" -a -f "$AA_EV_PIDFILE" ] ; then
sd_action "Shutting down AppArmor Event daemon" /sbin/killproc -G -p $AA_EV_PIDFILE -INT $AA_EV_BIN
fi
if [ -f "$SD_EV_PIDFILE" ] ; then
sd_action "Shutting down AppArmor Event daemon" /sbin/killproc -G -p $SD_EV_PIDFILE -INT $SD_EV_BIN
fi
}
function subdomain_start() {
if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then
load_module
rc=$?
if [ $rc -ne 0 ] ; then
return $rc
fi
fi
if ! is_securityfs_mounted ; then
mount_securityfs
rc=$?
if [ $rc -ne 0 ] ; then
return $rc
fi
fi
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
sd_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
return 1
fi
configure_owlsm
if [ $(wc -l "$SFS_MOUNTPOINT/profiles" | awk '{print $1}') -eq 0 ] ; then
parse_profiles load
else
sd_log_warning_msg "Loading AppArmor profiles - AppArmor already loaded with profiles. Not loading profiles."
fi
}
function remove_profiles() {
# removing profiles as we directly read from subdomainfs
# doesn't work, since we are removing entries which screws up
# our position. Lets hope there are never enough profiles to
# overflow the variable
if ! is_securityfs_mounted ; then
sd_log_failure_msg "failed: is securityfs loaded?"
return 1
fi
if [ ! -w "$SFS_MOUNTPOINT/.remove" ] ; then
sd_log_failure_msg "failed: Do you have the correct privileges?"
return 1
fi
if [ ! -x "${PARSER}" ] ; then
sd_log_failure_msg "failed: unable to execute subdomain parser"
return 1
fi
retval=0
IFS=$'\n'
enforced_profiles=$(sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles")
for profile in $enforced_profiles ; do
sd_action " Removing profile: ${profile}" sh -c "echo \"$profile { }\" | $PARSER -R"
rc=$?
if [ ${rc} -ne 0 ] ; then
retval=${rc}
fi
done
if [ ${retval} -ne 0 ] ; then
waserror=1
fi
}
function subdomain_stop() {
stop_sd_event
sd_log_info_msg "Unloading AppArmor profiles"
remove_profiles
}
function subdomain_kill() {
stop_sd_event
unmount_securityfs
if grep -qE "^apparmor[[:space:]]" /proc/modules ; then
MODULE=apparmor
elif grep -qE "^subdomain[[:space:]]" /proc/modules ; then
MODULE=subdomain
else
MODULE=apparmor
fi
sd_action "Unloading AppArmor modules" /sbin/modprobe -r $MODULE
}
function __subdomain_restart() {
if [ ! -w "$SFS_MOUNTPOINT/.load" ] ; then
sd_log_failure_msg "Loading AppArmor profiles - failed, Do you have the correct privileges?"
return 4
fi
configure_owlsm
parse_profiles reload
PNAMES_LIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
profiles_names_list ${PNAMES_LIST}
MODULE_PLIST=$(mktemp ${APPARMOR_TMPDIR}/tmp.XXXXXXXX)
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | sort >"$MODULE_PLIST"
#profiles=$(cat $PNAMES_LIST | sort | comm -2 -3 "$MODULE_PLIST" -)
#for profile in $profiles ; do
IFS=$'\n' && for profile in $(cat $PNAMES_LIST | sort | comm -2 -3 "$MODULE_PLIST" -) ; do
echo "\"$profile\" {}" | $PARSER -R >/dev/null
done
rm "$MODULE_PLIST"
rm "$PNAMES_LIST"
return 0
}
function subdomain_restart() {
if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then
subdomain_start
rc=$?
return $rc
fi
if ! is_securityfs_mounted ; then
mount_securityfs
rc=$?
if [ $rc -ne 0 ] ; then
return $rc
fi
fi
__subdomain_restart
rc=$?
return $rc
}
function subdomain_try_restart() {
if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then
return 1
fi
if ! is_securityfs_mounted ; then
return 1
fi
__subdomain_restart
rc=$?
return $rc
}
function subdomain_debug() {
subdomain_kill
load_module "subdomain_debug=1"
mount_securityfs
configure_owlsm
parse_profiles load
}
function configure_owlsm () {
if [ "${SUBDOMAIN_ENABLE_OWLSM}" = "yes" -a -f ${SFS_MOUNTPOINT}/control/owlsm ] ; then
# Sigh, the "sh -c" is necessary for the SuSE sd_action
# and it can't be abstracted out as a seperate function, as
# that breaks under RedHat's action, which needs a
# binary to invoke.
sd_action "Enabling OWLSM extension" sh -c "echo -n \"1\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
elif [ -f "${SFS_MOUNTPOINT}/control/owlsm" ] ; then
sd_action "Disabling OWLSM extension" sh -c "echo -n \"0\" > \"${SFS_MOUNTPOINT}/control/owlsm\""
fi
}
function subdomain_status () {
if test -x ${AA_STATUS} ; then
${AA_STATUS} --verbose
return $?
fi
if test -x ${SD_STATUS} ; then
${SD_STATUS} --verbose
return $?
fi
if ! grep -qE "^(subdomain|apparmor)[[:space:]]" /proc/modules ; then
sd_log_failure_msg "AppArmor not loaded."
rc=1
else
sd_log_success_msg "AppArmor module enabled."
rc=0
fi
sd_log_warning_msg "Install the apparmor-utils package to receive more detailed"
sd_log_warning_msg "status information here (or examine ${SFS_MOUNTPOINT} directly)."
return $rc
}

View File

@ -0,0 +1,38 @@
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
waserror=0
function sd_action() {
MSG=$1
shift
#echo "ACTION: $*"
$* > /dev/null
rc=$?
if [ $rc -ne 0 ] ; then
sd_log_failure_msg $"$MSG"
else
sd_log_success_msg $"$MSG"
fi
return $rc
}
function sd_log_info_msg() {
einfo " $1"
}
function sd_log_warning_msg() {
ewarn " $1"
}
function sd_log_success_msg() {
einfo " $1"
eend 0
}
function sd_log_failure_msg() {
waserror=1
einfo " $1"
eend 1
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<herd>maintainer-wanted</herd>
</pkgmetadata>

View File

@ -0,0 +1,23 @@
# ChangeLog for sys-kernel/apparmor-sources
# Copyright 1999-2006 Gentoo Foundation; Distributed under the GPL v2
# $Header: $
13 Aug 2006; Mario Fetka <mario-fetka@gmx.at>
+files/5000_apparmor-integrate.patch,
+files/5001_apparmor-core-header.patch,
+files/5002_apparmor-lsm-interface.patch,
+files/5004_apparmor-filesystem.patch, +apparmor-sources-2.6.17.ebuild,
+files/5003_apparmor-core-access-controls.patch,
+files/5006_apparmor-misc.patch, +files/5008_apparmor-audit-changes.patch,
+apparmor-sources-2.6.17-r1.ebuild,
+files/apparmor-sources-2.6.17-r1-apparmor_main.patch,
+files/5007_apparmor-pathname-matching-submodule.patch,
+files/5010_apparmor-export-namespace-semaphor.patch,
+files/apparmor-sources-2.6.17-r1-apparmor_audit.patch,
+files/apparmor-sources-2.6.17-r1-apparmor_namespacesem.patch,
+files/5005_apparmor-userspace-interface.patch,
+files/5009_apparmor-add-flags.patch:
Initial Import of
Matthew Snelham <zeypher@sigalrm.com>
Apparmor ebuilds

View File

@ -0,0 +1,73 @@
AUX 5000_apparmor-integrate.patch 2398 RMD160 4f3100e01a64531217137303b151d4b8f57cb5ea SHA1 c61a433e8449cd2e173eaf4526de807cd074d12b SHA256 558a025803b209d2502562553e7ec1a42dde706c6a3de4d1a442f4a4a17e8b89
MD5 d98fc30c0c02d3b6e1fdb5a56973ed67 files/5000_apparmor-integrate.patch 2398
RMD160 4f3100e01a64531217137303b151d4b8f57cb5ea files/5000_apparmor-integrate.patch 2398
SHA256 558a025803b209d2502562553e7ec1a42dde706c6a3de4d1a442f4a4a17e8b89 files/5000_apparmor-integrate.patch 2398
AUX 5001_apparmor-core-header.patch 21692 RMD160 d991a62378cf9394ed785ce170567c5a1636ed3a SHA1 6646b0ab9603356241ca09ac26093649b264e6f5 SHA256 104c8a90f300b967937d2930bfdb46fccc14d1c33e0eeeaccc2539795b02c9f7
MD5 589ca3ad54269790ce4ff0ac86bf1e22 files/5001_apparmor-core-header.patch 21692
RMD160 d991a62378cf9394ed785ce170567c5a1636ed3a files/5001_apparmor-core-header.patch 21692
SHA256 104c8a90f300b967937d2930bfdb46fccc14d1c33e0eeeaccc2539795b02c9f7 files/5001_apparmor-core-header.patch 21692
AUX 5002_apparmor-lsm-interface.patch 21459 RMD160 b61ddaab908a7a790472d7de3c0ee03dfe576489 SHA1 464d3806b9db782adfba98e37884f538f4f02fdd SHA256 8f22edd4509598b9188ef05b47028a745905af4402482f1698bf123f66d3b407
MD5 2ef63832bbbef8442cbf8a08d0279425 files/5002_apparmor-lsm-interface.patch 21459
RMD160 b61ddaab908a7a790472d7de3c0ee03dfe576489 files/5002_apparmor-lsm-interface.patch 21459
SHA256 8f22edd4509598b9188ef05b47028a745905af4402482f1698bf123f66d3b407 files/5002_apparmor-lsm-interface.patch 21459
AUX 5003_apparmor-core-access-controls.patch 42703 RMD160 fa685b1526b69cc5e436707b0e94513c963cf7e5 SHA1 756e4adac0c15e216b21c4b86bd390d2318f2092 SHA256 585f135ce0b07bc325503cccd5da07afa559ca75c9c3c0aeef3b1309f59aacb5
MD5 282fc71ae3ba0b0f37b10e856cb0bbb7 files/5003_apparmor-core-access-controls.patch 42703
RMD160 fa685b1526b69cc5e436707b0e94513c963cf7e5 files/5003_apparmor-core-access-controls.patch 42703
SHA256 585f135ce0b07bc325503cccd5da07afa559ca75c9c3c0aeef3b1309f59aacb5 files/5003_apparmor-core-access-controls.patch 42703
AUX 5004_apparmor-filesystem.patch 11823 RMD160 c356279b0a7aa3c86b7e61fa4fd19fcae01e4e28 SHA1 7bac3503d5d3c1c89c3c83824ce4db5fb4b76d4d SHA256 8ff511068c44f09fa9e9b0892323876373a0dd20cbdafab1847439fb7293228a
MD5 9b00001fd17410a6c5c8d93e1d791a4f files/5004_apparmor-filesystem.patch 11823
RMD160 c356279b0a7aa3c86b7e61fa4fd19fcae01e4e28 files/5004_apparmor-filesystem.patch 11823
SHA256 8ff511068c44f09fa9e9b0892323876373a0dd20cbdafab1847439fb7293228a files/5004_apparmor-filesystem.patch 11823
AUX 5005_apparmor-userspace-interface.patch 25246 RMD160 1aa62cbead83275308c9b2e5bf3658261d1a9381 SHA1 93a99de540ffbec0946192851832b823956cb3a6 SHA256 970934bf9e9d9a4e98e4d78eb4540d1b8d5409f5c97bbbd266ae473b7263d92f
MD5 f9ca3674c76ad58917df78d9ca55a461 files/5005_apparmor-userspace-interface.patch 25246
RMD160 1aa62cbead83275308c9b2e5bf3658261d1a9381 files/5005_apparmor-userspace-interface.patch 25246
SHA256 970934bf9e9d9a4e98e4d78eb4540d1b8d5409f5c97bbbd266ae473b7263d92f files/5005_apparmor-userspace-interface.patch 25246
AUX 5006_apparmor-misc.patch 16419 RMD160 7be689597785f339dd8d8d41fc46c48283acd329 SHA1 728e32285aeb1e8e7ef28c2d8aa8a775ad4b1ab2 SHA256 c44468fd5a698d11095cccb439541feac587388f348bec5f8105449294e1b8f6
MD5 eda12351340ca5e03ce2df5be7ab1396 files/5006_apparmor-misc.patch 16419
RMD160 7be689597785f339dd8d8d41fc46c48283acd329 files/5006_apparmor-misc.patch 16419
SHA256 c44468fd5a698d11095cccb439541feac587388f348bec5f8105449294e1b8f6 files/5006_apparmor-misc.patch 16419
AUX 5007_apparmor-pathname-matching-submodule.patch 7130 RMD160 53203c04619a1d1491f32af7b67d645cab2b42fd SHA1 f6e08796e9de778de5614f7dc0b3226ec3e0c886 SHA256 08f8cef053a986ac38130743cba28a584c0539f1e7d370cdff3e829e4cd48567
MD5 2d77b49c08b0f975660174c410f57cfe files/5007_apparmor-pathname-matching-submodule.patch 7130
RMD160 53203c04619a1d1491f32af7b67d645cab2b42fd files/5007_apparmor-pathname-matching-submodule.patch 7130
SHA256 08f8cef053a986ac38130743cba28a584c0539f1e7d370cdff3e829e4cd48567 files/5007_apparmor-pathname-matching-submodule.patch 7130
AUX 5008_apparmor-audit-changes.patch 2107 RMD160 d333371405ac7c595763bc35f312784cc811d366 SHA1 8801e85d409017c6693656b9e41973703170cad8 SHA256 adfed39273b71c470f8eebddf43f0eef2146b3114e517eb574f033005f5a95e5
MD5 2a4a92e7b58dafaee09f69fa05ebd89a files/5008_apparmor-audit-changes.patch 2107
RMD160 d333371405ac7c595763bc35f312784cc811d366 files/5008_apparmor-audit-changes.patch 2107
SHA256 adfed39273b71c470f8eebddf43f0eef2146b3114e517eb574f033005f5a95e5 files/5008_apparmor-audit-changes.patch 2107
AUX 5009_apparmor-add-flags.patch 5477 RMD160 fc48784cb74cba9cdbdf61c2f561e8951152344e SHA1 f70cad7a35362ff584991c70c1b481127e4b3799 SHA256 adae3a61e66d527586d8118b94843b3021b4c99224d2d8888e37f7dbed5ef783
MD5 29efc91d396797479864537b9f1e1b6f files/5009_apparmor-add-flags.patch 5477
RMD160 fc48784cb74cba9cdbdf61c2f561e8951152344e files/5009_apparmor-add-flags.patch 5477
SHA256 adae3a61e66d527586d8118b94843b3021b4c99224d2d8888e37f7dbed5ef783 files/5009_apparmor-add-flags.patch 5477
AUX 5010_apparmor-export-namespace-semaphor.patch 2052 RMD160 70bae68ca3aef38c9aea0b4add916fc759efb420 SHA1 4f553490593ebaddec1a8695e6da471466e4cc70 SHA256 42fd27dc8e65a450b6369638495ebcd1d615a23881f4ff7c4a8a334ac6e1e00a
MD5 5d38d075644b24d5018152b2b4a29514 files/5010_apparmor-export-namespace-semaphor.patch 2052
RMD160 70bae68ca3aef38c9aea0b4add916fc759efb420 files/5010_apparmor-export-namespace-semaphor.patch 2052
SHA256 42fd27dc8e65a450b6369638495ebcd1d615a23881f4ff7c4a8a334ac6e1e00a files/5010_apparmor-export-namespace-semaphor.patch 2052
AUX apparmor-sources-2.6.17-r1-apparmor_audit.patch 2247 RMD160 d6c5937273d30de4a83a42ad9256416bf2931a03 SHA1 113abbb7664e6cf205606c78c39086c4aea5883d SHA256 27b8c610ec1dd4b6b8474194061a6616359aa942f3dddf3ae197cadeea8e411c
MD5 aa55bffe2d0bf05ef6b6281dfb4c459c files/apparmor-sources-2.6.17-r1-apparmor_audit.patch 2247
RMD160 d6c5937273d30de4a83a42ad9256416bf2931a03 files/apparmor-sources-2.6.17-r1-apparmor_audit.patch 2247
SHA256 27b8c610ec1dd4b6b8474194061a6616359aa942f3dddf3ae197cadeea8e411c files/apparmor-sources-2.6.17-r1-apparmor_audit.patch 2247
AUX apparmor-sources-2.6.17-r1-apparmor_main.patch 219968 RMD160 8ac7a4ee65da4180684634b82bd468e2ff0ff790 SHA1 610451e2eb4c7b03ed4a37d527543dea8a0f6743 SHA256 f799f9f570dd1de355aad61a3583a6e06aba6138f4b7c064274ad524d4c6ab18
MD5 665706462da47fc5dde62b016bb6af49 files/apparmor-sources-2.6.17-r1-apparmor_main.patch 219968
RMD160 8ac7a4ee65da4180684634b82bd468e2ff0ff790 files/apparmor-sources-2.6.17-r1-apparmor_main.patch 219968
SHA256 f799f9f570dd1de355aad61a3583a6e06aba6138f4b7c064274ad524d4c6ab18 files/apparmor-sources-2.6.17-r1-apparmor_main.patch 219968
AUX apparmor-sources-2.6.17-r1-apparmor_namespacesem.patch 1197 RMD160 99acdb25d6384f650edb2914fb05205abe2a4f48 SHA1 21ee82c1bc2089f8af1985fcc57049422f5e02ba SHA256 1c6c97d3ef47c3b21e335246fabc4dbdb446e5fd638250a928ed62c8277ac015
MD5 ebc4034d4b5410191a67a3d5f2e7d82b files/apparmor-sources-2.6.17-r1-apparmor_namespacesem.patch 1197
RMD160 99acdb25d6384f650edb2914fb05205abe2a4f48 files/apparmor-sources-2.6.17-r1-apparmor_namespacesem.patch 1197
SHA256 1c6c97d3ef47c3b21e335246fabc4dbdb446e5fd638250a928ed62c8277ac015 files/apparmor-sources-2.6.17-r1-apparmor_namespacesem.patch 1197
DIST genpatches-2.6.17-1.base.tar.bz2 3337 RMD160 f9b5621fed8fcfee7da697d89097842287b41b24 SHA1 308e3daec11899f03103b5dcd2bfcff7e116c52c SHA256 2208b72729dce6daef7dc5700192aec0ae17327c794681621d2123f0c483ae21
DIST genpatches-2.6.17-1.extras.tar.bz2 138704 RMD160 14b17e02b7893e6b023bee9e1b40f4bc85a30f05 SHA1 e671dbc29239116e627aea3d87ff7aefd8b5ca00 SHA256 fa10ec7d3d74c8bf57fb3bd01c33f83dcca3c1e4cd4601937cc2ef904cce1dfe
DIST linux-2.6.17.tar.bz2 41272919 RMD160 26aad30c9a6610665c6c7d62401d79bf56a6a699 SHA1 0605c975b9dead2af31a3decf09dd4138fadaf2b SHA256 ab0f647d52f124958439517df9e1ae0efda90cdb851f59f522fa1749f1d87d58
EBUILD apparmor-sources-2.6.17-r1.ebuild 1142 RMD160 1a66dbec96105e2c33287e35839841abb431f6a3 SHA1 38f3b1e29e4d69babc6a9fc0667ad4048d7d09f1 SHA256 49ac1068e9ae0633574904d2f7a939a12916b19cc3a8909bbc8b3561f391ea12
MD5 90cb28e5a5b500a6373f5ced5162526f apparmor-sources-2.6.17-r1.ebuild 1142
RMD160 1a66dbec96105e2c33287e35839841abb431f6a3 apparmor-sources-2.6.17-r1.ebuild 1142
SHA256 49ac1068e9ae0633574904d2f7a939a12916b19cc3a8909bbc8b3561f391ea12 apparmor-sources-2.6.17-r1.ebuild 1142
EBUILD apparmor-sources-2.6.17.ebuild 977 RMD160 ac4b79962d1397e0402b8d77cfb0122847267487 SHA1 78a3d9b6a412f77ac498235e8cdfba3e2de5f420 SHA256 d2233bcc23eca9bbc84ffb74ed8ce93fee706a8a0f514dc3967e62e656bd46cd
MD5 0385b5fae689c746f3ddc97ac97809c1 apparmor-sources-2.6.17.ebuild 977
RMD160 ac4b79962d1397e0402b8d77cfb0122847267487 apparmor-sources-2.6.17.ebuild 977
SHA256 d2233bcc23eca9bbc84ffb74ed8ce93fee706a8a0f514dc3967e62e656bd46cd apparmor-sources-2.6.17.ebuild 977
MD5 0e1ade0aa9228c7dad088db16e4f1d3a files/digest-apparmor-sources-2.6.17 801
RMD160 74e1080cfdd78f0b7cc0314a2822efbe02ec2333 files/digest-apparmor-sources-2.6.17 801
SHA256 482238abaafe1482e35b0de5d6fbde3cc5f3e307aa885f823693b5bf01edcc09 files/digest-apparmor-sources-2.6.17 801
MD5 0e1ade0aa9228c7dad088db16e4f1d3a files/digest-apparmor-sources-2.6.17-r1 801
RMD160 74e1080cfdd78f0b7cc0314a2822efbe02ec2333 files/digest-apparmor-sources-2.6.17-r1 801
SHA256 482238abaafe1482e35b0de5d6fbde3cc5f3e307aa885f823693b5bf01edcc09 files/digest-apparmor-sources-2.6.17-r1 801

View File

@ -0,0 +1,43 @@
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
ETYPE="sources"
K_WANT_GENPATCHES="base extras"
K_GENPATCHES_VER="1"
inherit eutils kernel-2
detect_version
detect_arch
KEYWORDS="~x86 ~amd64"
HOMEPAGE="http://forge.novell.com/modules/xfmod/project/?apparmor"
DESCRIPTION="Full sources to provide the required AppArmor modules and kernel hooks. Based on the gentoo-sources tree."
SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
src_unpack() {
ABI=${KERNEL_ABI}
kernel-2_src_unpack
EPATCH_FORCE="yes"
EPATCH_OPTS=""
epatch ${FILESDIR}/${PF}*.patch
}
pkg_postinst() {
postinst_sources
einfo
einfo "For more info on this patchset, and how to report problems, see:"
einfo "${HOMEPAGE}"
einfo
einfo "Make sure that your kernel configuration file is set with:"
einfo " CONFIG_SECURITY=y"
einfo " CONFIG_SECURITY_APPARMOR=m"
einfo "Without these, apparmor will not function."
einfo
einfo "Apparmor can be sensitive to module load order. Make sure"
einfo "it is listed before any other modules that rely on the "
einfo "'capability' module."
}

View File

@ -0,0 +1,39 @@
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
ETYPE="sources"
K_WANT_GENPATCHES="base extras"
K_GENPATCHES_VER="1"
inherit eutils kernel-2
detect_version
detect_arch
KEYWORDS="~x86 ~amd64"
HOMEPAGE="http://forge.novell.com/modules/xfmod/project/?apparmor"
DESCRIPTION="Full sources to provide the required AppArmor modules and kernel hooks. Based on the gentoo-sources tree."
SRC_URI="${KERNEL_URI} ${GENPATCHES_URI} ${ARCH_URI}"
src_unpack() {
ABI=${KERNEL_ABI}
kernel-2_src_unpack
EPATCH_FORCE="yes"
EPATCH_OPTS=""
epatch ${FILESDIR}/*_apparmor-*.patch
}
pkg_postinst() {
postinst_sources
einfo
einfo "For more info on this patchset, and how to report problems, see:"
einfo "${HOMEPAGE}"
einfo
einfo "Make sure that your kernel configuration file is set with:"
einfo " CONFIG_SECURITY=y"
einfo " CONFIG_SECURITY_APPARMOR=m"
einfo "Without these, apparmor will not function."
}

View File

@ -0,0 +1,76 @@
This patch glues AppArmor into the security configuration and Makefile.
It also creates the AppArmor configuration and Makefile.
Signed-off-by: Tony Jones <tonyj@suse.de>
---
MAINTAINERS | 7 +++++++
security/Kconfig | 1 +
security/Makefile | 1 +
security/apparmor/Kconfig | 9 +++++++++
security/apparmor/Makefile | 6 ++++++
5 files changed, 24 insertions(+)
--- linux-2.6.17-rc1.orig/MAINTAINERS
+++ linux-2.6.17-rc1/MAINTAINERS
@@ -284,6 +284,13 @@
W: http://www.canb.auug.org.au/~sfr/
S: Supported
+APPARMOR SECURITY MODULE
+P: Tony Jones
+M: tonyj@suse.de
+L: apparmor-dev@forge.novell.com
+W: http://forge.novell.com/modules/xfmod/project/?apparmor
+S: Supported
+
APPLETALK NETWORK LAYER
P: Arnaldo Carvalho de Melo
M: acme@conectiva.com.br
--- linux-2.6.17-rc1.orig/security/Kconfig
+++ linux-2.6.17-rc1/security/Kconfig
@@ -100,6 +100,7 @@
If you are unsure how to answer this question, answer N.
source security/selinux/Kconfig
+source security/apparmor/Kconfig
endmenu
--- linux-2.6.17-rc1.orig/security/Makefile
+++ linux-2.6.17-rc1/security/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_KEYS) += keys/
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
+subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
# if we don't select a security model, use the default capabilities
ifneq ($(CONFIG_SECURITY),y)
--- /dev/null
+++ linux-2.6.17-rc1/security/apparmor/Kconfig
@@ -0,0 +1,9 @@
+config SECURITY_APPARMOR
+ tristate "AppArmor support"
+ depends on SECURITY!=n
+ help
+ This enables the AppArmor security module.
+ Required userspace tools (if they are not included in your
+ distribution) and further information may be found at
+ <http://forge.novell.com/modules/xfmod/project/?apparmor>
+ If you are unsure how to answer this question, answer N.
--- /dev/null
+++ linux-2.6.17-rc1/security/apparmor/Makefile
@@ -0,0 +1,6 @@
+# Makefile for AppArmor Linux Security Module
+#
+subdir-$(CONFIG_SECURITY_APPARMOR) += match
+obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
+
+apparmor-y := main.o list.o procattr.o lsm.o apparmorfs.o capabilities.o module_interface.o
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,728 @@
This patch provides the various common headerfiles used by the AppArmor module.
apparmor.h contains the core data structures.
shared.h contains definitions that are common to the userspace policy loader.
inline.h implements various inline utility functions
Signed-off-by: Tony Jones <tonyj@suse.de>
---
security/apparmor/apparmor.h | 325 +++++++++++++++++++++++++++++++++++++++++
security/apparmor/inline.h | 333 +++++++++++++++++++++++++++++++++++++++++++
security/apparmor/shared.h | 41 +++++
3 files changed, 699 insertions(+)
--- security/apparmor/apparmor.h.orig
+++ security/apparmor/apparmor.h
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 1998-2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * AppArmor internal prototypes
+ */
+
+#ifndef __SUBDOMAIN_H
+#define __SUBDOMAIN_H
+
+#include <linux/fs.h> /* Include for defn of iattr */
+#include <linux/rcupdate.h>
+
+#include "shared.h"
+
+/* Control parameters (0 or 1), settable thru module/boot flags or
+ * via /sys/kernel/security/apparmor/control */
+extern int apparmor_complain;
+extern int apparmor_debug;
+extern int apparmor_audit;
+extern int apparmor_logsyscall;
+
+/* PIPEFS_MAGIC */
+#include <linux/pipe_fs_i.h>
+/* from net/socket.c */
+#define SOCKFS_MAGIC 0x534F434B
+/* from inotify.c */
+#define INOTIFYFS_MAGIC 0xBAD1DEA
+
+#define VALID_FSTYPE(inode) ((inode)->i_sb->s_magic != PIPEFS_MAGIC && \
+ (inode)->i_sb->s_magic != SOCKFS_MAGIC && \
+ (inode)->i_sb->s_magic != INOTIFYFS_MAGIC)
+
+#define PROFILE_COMPLAIN(_profile) \
+ (apparmor_complain == 1 || ((_profile) && (_profile)->flags.complain))
+
+#define SUBDOMAIN_COMPLAIN(_sd) \
+ (apparmor_complain == 1 || \
+ ((_sd) && (_sd)->active && (_sd)->active->flags.complain))
+
+#define PROFILE_AUDIT(_profile) \
+ (apparmor_audit == 1 || ((_profile) && (_profile)->flags.audit))
+
+#define SUBDOMAIN_AUDIT(_sd) \
+ (apparmor_audit == 1 || \
+ ((_sd) && (_sd)->active && (_sd)->active->flags.audit))
+
+/*
+ * DEBUG remains global (no per profile flag) since it is mostly used in sysctl
+ * which is not related to profile accesses.
+ */
+
+#define AA_DEBUG(fmt, args...) \
+ do { \
+ if (apparmor_debug) \
+ printk(KERN_DEBUG "AppArmor: " fmt, ##args); \
+ } while (0)
+#define AA_INFO(fmt, args...) printk(KERN_INFO "AppArmor: " fmt, ##args)
+#define AA_WARN(fmt, args...) printk(KERN_WARNING "AppArmor: " fmt, ##args)
+#define AA_ERROR(fmt, args...) printk(KERN_ERR "AppArmor: " fmt, ##args)
+
+/* basic AppArmor data structures */
+
+struct flagval {
+ int debug;
+ int complain;
+ int audit;
+};
+
+enum entry_match_type {
+ aa_entry_literal,
+ aa_entry_tailglob,
+ aa_entry_pattern,
+ aa_entry_invalid
+};
+
+/* struct aa_entry - file ACL *
+ * @filename: filename controlled by this ACL
+ * @mode: permissions granted by ACL
+ * @type: type of match to perform against @filename
+ * @extradata: any extra data needed by an extended matching type
+ * @list: list the ACL is on
+ * @listp: permission partitioned lists this ACL is on.
+ *
+ * Each entry describes a file and an allowed access mode.
+ */
+struct aa_entry {
+ char *filename;
+ int mode; /* mode is 'or' of READ, WRITE, EXECUTE,
+ * INHERIT, UNCONSTRAINED, and LIBRARY
+ * (meaning don't prefetch). */
+
+ enum entry_match_type type;
+ void *extradata;
+
+ struct list_head list;
+ struct list_head listp[POS_AA_FILE_MAX + 1];
+};
+
+#define AA_EXEC_MODIFIER_MASK(mask) ((mask) & (AA_EXEC_UNCONSTRAINED |\
+ AA_EXEC_INHERIT |\
+ AA_EXEC_PROFILE))
+
+#define AA_EXEC_MASK(mask) ((mask) & (AA_MAY_EXEC |\
+ AA_EXEC_UNCONSTRAINED |\
+ AA_EXEC_INHERIT |\
+ AA_EXEC_PROFILE))
+
+
+/* struct aaprofile - basic confinement data
+ * @parent: non refcounted pointer to parent profile
+ * @name: the profiles name
+ * @file_entry: file ACL
+ * @file_entryp: vector of file ACL by permission granted
+ * @list: list this profile is on
+ * @sub: profiles list of subprofiles (HATS)
+ * @flags: flags controlling profile behavior
+ * @null_profile: if needed per profile learning and null confinement profile
+ * @isstale: flag to indicate the profile is stale
+ * @num_file_entries: number of file entries the profile contains
+ * @num_file_pentries: number of file entries for each partitioned list
+ * @capabilities: capabilities granted by the process
+ * @rcu: rcu head used when freeing the profile
+ * @count: reference count of the profile
+ *
+ * The AppArmor profile contains the basic confinement data. Each profile
+ * has a name and potentially a list of profile entries. The profiles are
+ * connected in a list
+ */
+struct aaprofile {
+ struct aaprofile *parent;
+ char *name;
+
+ struct list_head file_entry;
+ struct list_head file_entryp[POS_AA_FILE_MAX + 1];
+ struct list_head list;
+ struct list_head sub;
+ struct flagval flags;
+ struct aaprofile *null_profile;
+ int isstale;
+
+ int num_file_entries;
+ int num_file_pentries[POS_AA_FILE_MAX + 1];
+
+ kernel_cap_t capabilities;
+
+ struct rcu_head rcu;
+
+ struct kref count;
+};
+
+/**
+ * struct subdomain - primary label for confined tasks
+ * @active: the current active profile
+ * @hat_magic: the magic token controling the ability to leave a hat
+ * @list: list this subdomain is on
+ * @task: task that the subdomain confines
+ *
+ * Contains the tasks current active profile (which could change due to
+ * change_hat). Plus the hat_magic needed during change_hat.
+ *
+ * N.B AppArmor's previous product name SubDomain was derived from the name
+ * of this structure/concept (changehat reducing a task into a sub-domain).
+ */
+struct subdomain {
+ struct aaprofile *active; /* The current active profile */
+ u32 hat_magic; /* used with change_hat */
+ struct list_head list; /* list of subdomains */
+ struct task_struct *task;
+};
+
+typedef int (*aa_iter) (struct subdomain *, void *);
+
+/* aa_path_data
+ * temp (cookie) data used by aa_path_* functions, see inline.h
+ */
+struct aa_path_data {
+ struct dentry *root, *dentry;
+ struct namespace *namespace;
+ struct list_head *head, *pos;
+ int errno;
+};
+
+#define AA_SUBDOMAIN(sec) ((struct subdomain*)(sec))
+#define AA_PROFILE(sec) ((struct aaprofile*)(sec))
+
+/* Lock protecting access to 'struct subdomain' accesses */
+extern spinlock_t sd_lock;
+
+extern struct aaprofile *null_complain_profile;
+
+/* aa_audit - AppArmor auditing structure
+ * Structure is populated by access control code and passed to aa_audit which
+ * provides for a single point of logging.
+ */
+
+struct aa_audit {
+ unsigned short type, flags;
+ unsigned int result;
+ unsigned int gfp_mask;
+ int error_code;
+
+ const char *name;
+ unsigned int ival;
+ union {
+ const void *pval;
+ va_list vaval;
+ };
+};
+
+/* audit types */
+#define AA_AUDITTYPE_FILE 1
+#define AA_AUDITTYPE_DIR 2
+#define AA_AUDITTYPE_ATTR 3
+#define AA_AUDITTYPE_XATTR 4
+#define AA_AUDITTYPE_LINK 5
+#define AA_AUDITTYPE_CAP 6
+#define AA_AUDITTYPE_MSG 7
+#define AA_AUDITTYPE_SYSCALL 8
+#define AA_AUDITTYPE__END 9
+
+/* audit flags */
+#define AA_AUDITFLAG_AUDITSS_SYSCALL 1 /* log syscall context */
+#define AA_AUDITFLAG_LOGERR 2 /* log operations that failed due to
+ non permission errors */
+
+#define HINT_UNKNOWN_HAT "unknown_hat"
+#define HINT_FORK "fork"
+#define HINT_MANDPROF "missing_mandatory_profile"
+#define HINT_CHGPROF "changing_profile"
+
+#define LOG_HINT(p, gfp, hint, fmt, args...) \
+ do {\
+ aa_audit_message(p, gfp, 0, \
+ "LOGPROF-HINT " hint " " fmt, ##args);\
+ } while(0)
+
+/* directory op type, for aa_perm_dir */
+enum aa_diroptype {
+ aa_dir_mkdir,
+ aa_dir_rmdir
+};
+
+/* xattr op type, for aa_xattr */
+enum aa_xattroptype {
+ aa_xattr_get,
+ aa_xattr_set,
+ aa_xattr_list,
+ aa_xattr_remove
+};
+
+#define BASE_PROFILE(p) ((p)->parent ? (p)->parent : (p))
+#define IN_SUBPROFILE(p) ((p)->parent)
+
+/* main.c */
+extern int alloc_null_complain_profile(void);
+extern void free_null_complain_profile(void);
+extern int attach_nullprofile(struct aaprofile *profile);
+extern int aa_audit_message(struct aaprofile *active, unsigned int gfp, int,
+ const char *, ...);
+extern int aa_audit_syscallreject(struct aaprofile *active, unsigned int gfp,
+ const char *);
+extern int aa_audit(struct aaprofile *active, const struct aa_audit *);
+extern char *aa_get_name(struct dentry *dentry, struct vfsmount *mnt);
+
+extern int aa_attr(struct aaprofile *active, struct dentry *dentry,
+ struct iattr *iattr);
+extern int aa_xattr(struct aaprofile *active, struct dentry *dentry,
+ const char *xattr, enum aa_xattroptype xattroptype);
+extern int aa_capability(struct aaprofile *active, int cap);
+extern int aa_perm(struct aaprofile *active, struct dentry *dentry,
+ struct vfsmount *mnt, int mask);
+extern int aa_perm_nameidata(struct aaprofile *active, struct nameidata *nd,
+ int mask);
+extern int aa_perm_dentry(struct aaprofile *active, struct dentry *dentry,
+ int mask);
+extern int aa_perm_dir(struct aaprofile *active, struct dentry *dentry,
+ enum aa_diroptype diroptype);
+extern int aa_link(struct aaprofile *active,
+ struct dentry *link, struct dentry *target);
+extern int aa_fork(struct task_struct *p);
+extern int aa_register(struct file *file);
+extern void aa_release(struct task_struct *p);
+extern int aa_change_hat(const char *id, u32 hat_magic);
+extern int aa_associate_filp(struct file *filp);
+
+/* list.c */
+extern struct aaprofile *aa_profilelist_find(const char *name);
+extern int aa_profilelist_add(struct aaprofile *profile);
+extern struct aaprofile *aa_profilelist_remove(const char *name);
+extern void aa_profilelist_release(void);
+extern struct aaprofile *aa_profilelist_replace(struct aaprofile *profile);
+extern void aa_profile_dump(struct aaprofile *);
+extern void aa_profilelist_dump(void);
+extern void aa_subdomainlist_add(struct subdomain *);
+extern void aa_subdomainlist_remove(struct subdomain *);
+extern void aa_subdomainlist_iterate(aa_iter, void *);
+extern void aa_subdomainlist_iterateremove(aa_iter, void *);
+extern void aa_subdomainlist_release(void);
+
+/* module_interface.c */
+extern ssize_t aa_file_prof_add(void *, size_t);
+extern ssize_t aa_file_prof_repl(void *, size_t);
+extern ssize_t aa_file_prof_remove(const char *, size_t);
+extern void free_aaprofile(struct aaprofile *profile);
+extern void free_aaprofile_kref(struct kref *kref);
+
+/* procattr.c */
+extern size_t aa_getprocattr(struct aaprofile *active, char *str, size_t size);
+extern int aa_setprocattr_changehat(char *hatinfo, size_t infosize);
+extern int aa_setprocattr_setprofile(struct task_struct *p, char *profilename,
+ size_t profilesize);
+
+/* apparmorfs.c */
+extern int create_apparmorfs(void);
+extern void destroy_apparmorfs(void);
+
+/* capabilities.c */
+extern const char *capability_to_name(unsigned int cap);
+
+#endif /* __SUBDOMAIN_H */
--- security/apparmor/inline.h.orig
+++ security/apparmor/inline.h
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#ifndef __INLINE_H
+#define __INLINE_H
+
+#include <linux/namespace.h>
+
+static inline int __aa_is_confined(struct subdomain *sd)
+{
+ return (sd && sd->active);
+}
+
+/**
+ * aa_is_confined
+ * Determine whether current task contains a valid profile (confined).
+ * Return %1 if confined, %0 otherwise.
+ */
+static inline int aa_is_confined(void)
+{
+ struct subdomain *sd = AA_SUBDOMAIN(current->security);
+ return __aa_is_confined(sd);
+}
+
+static inline int __aa_sub_defined(struct subdomain *sd)
+{
+ return __aa_is_confined(sd) && !list_empty(&BASE_PROFILE(sd->active)->sub);
+}
+
+/**
+ * aa_sub_defined - check to see if current task has any subprofiles
+ * Return 1 if true, 0 otherwise
+ */
+static inline int aa_sub_defined(void)
+{
+ struct subdomain *sd = AA_SUBDOMAIN(current->security);
+ return __aa_sub_defined(sd);
+}
+
+/**
+ * get_aaprofile - increment refcount on profile @p
+ * @p: profile
+ */
+static inline struct aaprofile *get_aaprofile(struct aaprofile *p)
+{
+ if (p)
+ kref_get(&(BASE_PROFILE(p)->count));
+
+ return p;
+}
+
+/**
+ * put_aaprofile - decrement refcount on profile @p
+ * @p: profile
+ */
+static inline void put_aaprofile(struct aaprofile *p)
+{
+ if (p)
+ kref_put(&BASE_PROFILE(p)->count, free_aaprofile_kref);
+}
+
+/**
+ * get_task_activeptr_rcu - get pointer to @tsk's active profile.
+ * @tsk: task to get active profile from
+ *
+ * Requires rcu_read_lock is held
+ */
+static inline struct aaprofile *get_task_activeptr_rcu(struct task_struct *tsk)
+{
+ struct subdomain *sd = AA_SUBDOMAIN(tsk->security);
+ struct aaprofile *active = NULL;
+
+ if (sd)
+ active = (struct aaprofile *) rcu_dereference(sd->active);
+
+ return active;
+}
+
+/**
+ * get_activeptr_rcu - get pointer to current task's active profile
+ * Requires rcu_read_lock is held
+ */
+static inline struct aaprofile *get_activeptr_rcu(void)
+{
+ return get_task_activeptr_rcu(current);
+}
+
+/**
+ * get_task_active_aaprofile - get a reference to tsk's active profile.
+ * @tsk: the task to get the active profile reference for
+ */
+static inline struct aaprofile *get_task_active_aaprofile(struct task_struct *tsk)
+{
+ struct aaprofile *active;
+
+ rcu_read_lock();
+ active = get_aaprofile(get_task_activeptr_rcu(tsk));
+ rcu_read_unlock();
+
+ return active;
+}
+
+/**
+ * get_active_aaprofile - get a reference to the current tasks active profile
+ */
+static inline struct aaprofile *get_active_aaprofile(void)
+{
+ return get_task_active_aaprofile(current);
+}
+
+/**
+ * aa_switch - change subdomain to use a new profile
+ * @sd: subdomain to switch the active profile on
+ * @newactive: new active profile
+ *
+ * aa_switch handles the changing of a subdomain's active profile. The
+ * sd_lock must be held to ensure consistency against other writers.
+ * Some write paths (ex. aa_register) require sd->active not to change
+ * over several operations, so the calling function is responsible
+ * for grabing the sd_lock to meet its consistency constraints before
+ * calling aa_switch
+ */
+static inline void aa_switch(struct subdomain *sd, struct aaprofile *newactive)
+{
+ struct aaprofile *oldactive = sd->active;
+
+ /* noop if NULL */
+ rcu_assign_pointer(sd->active, get_aaprofile(newactive));
+ put_aaprofile(oldactive);
+}
+
+/**
+ * aa_switch_unconfined - change subdomain to be unconfined (no profile)
+ * @sd: subdomain to switch
+ *
+ * aa_switch_unconfined handles the removal of a subdomain's active profile.
+ * The sd_lock must be held to ensure consistency against other writers.
+ * Like aa_switch the sd_lock is used to maintain consistency.
+ */
+static inline void aa_switch_unconfined(struct subdomain *sd)
+{
+ aa_switch(sd, NULL);
+
+ /* reset magic in case we were in a subhat before */
+ sd->hat_magic = 0;
+}
+
+/**
+ * alloc_subdomain - allocate a new subdomain
+ * @tsk: task struct
+ *
+ * Allocate a new subdomain including a backpointer to it's referring task.
+ */
+static inline struct subdomain *alloc_subdomain(struct task_struct *tsk)
+{
+ struct subdomain *sd;
+
+ sd = kzalloc(sizeof(struct subdomain), GFP_KERNEL);
+ if (!sd)
+ goto out;
+
+ /* back pointer to task */
+ sd->task = tsk;
+
+ /* any readers of the list must make sure that they can handle
+ * case where sd->active is not yet set (null)
+ */
+ aa_subdomainlist_add(sd);
+
+out:
+ return sd;
+}
+
+/**
+ * free_subdomain - Free a subdomain previously allocated by alloc_subdomain
+ * @sd: subdomain
+ */
+static inline void free_subdomain(struct subdomain *sd)
+{
+ aa_subdomainlist_remove(sd);
+ kfree(sd);
+}
+
+/**
+ * alloc_aaprofile - Allocate, initialize and return a new zeroed profile.
+ * Returns NULL on failure.
+ */
+static inline struct aaprofile *alloc_aaprofile(void)
+{
+ struct aaprofile *profile;
+
+ profile = (struct aaprofile *)kzalloc(sizeof(struct aaprofile),
+ GFP_KERNEL);
+ AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
+ if (profile) {
+ int i;
+
+ INIT_LIST_HEAD(&profile->list);
+ INIT_LIST_HEAD(&profile->sub);
+ INIT_LIST_HEAD(&profile->file_entry);
+ for (i = 0; i <= POS_AA_FILE_MAX; i++) {
+ INIT_LIST_HEAD(&profile->file_entryp[i]);
+ }
+ INIT_RCU_HEAD(&profile->rcu);
+ kref_init(&profile->count);
+ }
+ return profile;
+}
+
+/**
+ * aa_put_name
+ * @name: name to release.
+ *
+ * Release space (free_page) allocated to hold pathname
+ * name may be NULL (checked for by free_page)
+ */
+static inline void aa_put_name(const char *name)
+{
+ free_page((unsigned long)name);
+}
+
+/** __aa_find_profile
+ * @name: name of profile to find
+ * @head: list to search
+ *
+ * Return reference counted copy of profile. NULL if not found
+ * Caller must hold any necessary locks
+ */
+static inline struct aaprofile *__aa_find_profile(const char *name,
+ struct list_head *head)
+{
+ struct aaprofile *p;
+
+ if (!name || !head)
+ return NULL;
+
+ AA_DEBUG("%s: finding profile %s\n", __FUNCTION__, name);
+ list_for_each_entry(p, head, list) {
+ if (!strcmp(p->name, name)) {
+ /* return refcounted object */
+ p = get_aaprofile(p);
+ return p;
+ } else {
+ AA_DEBUG("%s: skipping %s\n", __FUNCTION__, p->name);
+ }
+ }
+ return NULL;
+}
+
+/** __aa_path_begin
+ * @rdentry: filesystem root dentry (searching for vfsmnts matching this)
+ * @dentry: dentry object to obtain pathname from (relative to matched vfsmnt)
+ *
+ * Setup data for iterating over vfsmounts (in current tasks namespace).
+ */
+static inline void __aa_path_begin(struct dentry *rdentry,
+ struct dentry *dentry,
+ struct aa_path_data *data)
+{
+ data->dentry = dentry;
+ data->root = dget(rdentry->d_sb->s_root);
+ data->namespace = current->namespace;
+ data->head = &data->namespace->list;
+ data->pos = data->head->next;
+ prefetch(data->pos->next);
+ data->errno = 0;
+
+ down_read(&namespace_sem);
+}
+
+/** aa_path_begin
+ * @dentry: filesystem root dentry and object to obtain pathname from
+ *
+ * Utility function for calling _aa_path_begin for when the dentry we are
+ * looking for and the root are the same (this is the usual case).
+ */
+static inline void aa_path_begin(struct dentry *dentry,
+ struct aa_path_data *data)
+{
+ __aa_path_begin(dentry, dentry, data);
+}
+
+/** aa_path_end
+ * @data: data object previously initialized by aa_path_begin
+ *
+ * End iterating over vfsmounts.
+ * If an error occured in begin or get, it is returned. Otherwise 0.
+ */
+static inline int aa_path_end(struct aa_path_data *data)
+{
+ up_read(&namespace_sem);
+ dput(data->root);
+
+ return data->errno;
+}
+
+/** aa_path_getname
+ * @data: data object previously initialized by aa_path_begin
+ *
+ * Return the next mountpoint which has the same root dentry as data->root.
+ * If no more mount points exist (or in case of error) NULL is returned
+ * (caller should call aa_path_end() and inspect return code to differentiate)
+ */
+static inline char *aa_path_getname(struct aa_path_data *data)
+{
+ char *name = NULL;
+ struct vfsmount *mnt;
+
+ while (data->pos != data->head) {
+ mnt = list_entry(data->pos, struct vfsmount, mnt_list);
+
+ /* advance to next -- so that it is done before we break */
+ data->pos = data->pos->next;
+ prefetch(data->pos->next);
+
+ if (mnt->mnt_root == data->root) {
+ name = aa_get_name(data->dentry, mnt);
+ if (!name)
+ data->errno = -ENOMEM;
+ break;
+ }
+ }
+
+ return name;
+}
+
+#endif /* __INLINE_H__ */
--- security/apparmor/shared.h.orig
+++ security/apparmor/shared.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2000, 2001, 2004, 2005 Novell/SUSE
+ *
+ * Immunix AppArmor LSM
+ *
+ * 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, version 2 of the
+ * License.
+ */
+
+#ifndef _SHARED_H
+#define _SHARED_H
+
+/* start of system offsets */
+#define POS_AA_FILE_MIN 0
+#define POS_AA_MAY_EXEC POS_AA_FILE_MIN
+#define POS_AA_MAY_WRITE (POS_AA_MAY_EXEC + 1)
+#define POS_AA_MAY_READ (POS_AA_MAY_WRITE + 1)
+#define POS_AA_MAY_APPEND (POS_AA_MAY_READ + 1)
+/* end of system offsets */
+
+#define POS_AA_MAY_LINK (POS_AA_MAY_APPEND + 1)
+#define POS_AA_EXEC_INHERIT (POS_AA_MAY_LINK + 1)
+#define POS_AA_EXEC_UNCONSTRAINED (POS_AA_EXEC_INHERIT + 1)
+#define POS_AA_EXEC_PROFILE (POS_AA_EXEC_UNCONSTRAINED + 1)
+#define POS_AA_FILE_MAX POS_AA_EXEC_PROFILE
+
+/* Modeled after MAY_READ, MAY_WRITE, MAY_EXEC def'ns */
+#define AA_MAY_EXEC (0x01 << POS_AA_MAY_EXEC)
+#define AA_MAY_WRITE (0x01 << POS_AA_MAY_WRITE)
+#define AA_MAY_READ (0x01 << POS_AA_MAY_READ)
+#define AA_MAY_LINK (0x01 << POS_AA_MAY_LINK)
+#define AA_EXEC_INHERIT (0x01 << POS_AA_EXEC_INHERIT)
+#define AA_EXEC_UNCONSTRAINED (0x01 << POS_AA_EXEC_UNCONSTRAINED)
+#define AA_EXEC_PROFILE (0x01 << POS_AA_EXEC_PROFILE)
+#define AA_EXEC_MODIFIERS(X) (X & (AA_EXEC_INHERIT | \
+ A_EXEC_UNCONSTRAINED | \
+ AA_EXEC_PROFILE))
+
+#endif /* _SHARED_H */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,880 @@
Implements the lsm interface used by AppArmor.
The code composes the functionality provided by commoncap therefore there
is no requirement for it to stack with the capability module.
See linux/include/security.h for a full description of all the LSM hooks.
Consistency of the subdomain (task) data is implemented on the reader side
via rcu. Logical consistency across profile replacement/removal and change
hat is provided via the spinlock sd_lock. Since profile manipulation and
change_hat are infrequent, most syscall accesses requires no spin lock.
Certain syscalls are prevented for confined processes. These are:
ptrace
mount
umount
sysctl writes also require CAP_SYS_ADMIN
File access checks are performed when a file is initially opened
(inode_permission) and cached to avoid revalidation unless where necessary
(passing descriptors between tasks confined with differing profiles, and
profile replacement, for example). Further patches are in development
to support caching of multiple profiles against an open file to minimise
the need for subsequent revalidation across profiles.
Signed-off-by: Tony Jones <tonyj@suse.de>
---
security/apparmor/lsm.c | 840 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 840 insertions(+)
--- security/apparmor/lsm.c.orig
+++ security/apparmor/lsm.c
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 2002-2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * http://forge.novell.com/modules/xfmod/project/?apparmor
+ *
+ * Immunix AppArmor LSM interface
+ */
+
+#include <linux/security.h>
+#include <linux/module.h>
+#include <linux/mman.h>
+
+#include "apparmor.h"
+#include "inline.h"
+
+/* struct subdomain write update lock (read side is RCU). */
+spinlock_t sd_lock = SPIN_LOCK_UNLOCKED;
+
+/* Flag values, also controllable via apparmorfs/control.
+ * We explicitly do not allow these to be modifiable when exported via
+ * /sys/modules/parameters, as we want to do additional mediation and
+ * don't want to add special path code. */
+
+/* Complain mode -- in complain mode access failures result in auditing only
+ * and task is allowed access. audit events are processed by userspace to
+ * generate policy. Default is 'enforce' (0).
+ * Value is also togglable per profile and referenced when global value is
+ * enforce.
+ */
+int apparmor_complain = 0;
+module_param_named(complain, apparmor_complain, int, S_IRUSR);
+MODULE_PARM_DESC(apparmor_complain, "Toggle AppArmor complain mode");
+
+/* Debug mode */
+int apparmor_debug = 0;
+module_param_named(debug, apparmor_debug, int, S_IRUSR);
+MODULE_PARM_DESC(apparmor_debug, "Toggle AppArmor debug mode");
+
+/* Audit mode */
+int apparmor_audit = 0;
+module_param_named(audit, apparmor_audit, int, S_IRUSR);
+MODULE_PARM_DESC(apparmor_audit, "Toggle AppArmor audit mode");
+
+/* Syscall logging mode */
+int apparmor_logsyscall = 0;
+module_param_named(logsyscall, apparmor_logsyscall, int, S_IRUSR);
+MODULE_PARM_DESC(apparmor_logsyscall, "Toggle AppArmor logsyscall mode");
+
+#ifndef MODULE
+static int __init aa_getopt_complain(char *str)
+{
+ get_option(&str, &apparmor_complain);
+ return 1;
+}
+__setup("apparmor_complain=", aa_getopt_complain);
+
+static int __init aa_getopt_debug(char *str)
+{
+ get_option(&str, &apparmor_debug);
+ return 1;
+}
+__setup("apparmor_debug=", aa_getopt_debug);
+
+static int __init aa_getopt_audit(char *str)
+{
+ get_option(&str, &apparmor_audit);
+ return 1;
+}
+__setup("apparmor_audit=", aa_getopt_audit);
+
+static int __init aa_getopt_logsyscall(char *str)
+{
+ get_option(&str, &apparmor_logsyscall);
+ return 1;
+}
+__setup("apparmor_logsyscall=", aa_getopt_logsyscall);
+#endif
+
+static int apparmor_ptrace(struct task_struct *parent,
+ struct task_struct *child)
+{
+ int error;
+ struct aaprofile *active;
+
+ error = cap_ptrace(parent, child);
+
+ active = get_active_aaprofile();
+
+ if (!error && active) {
+ error = aa_audit_syscallreject(active, GFP_KERNEL, "ptrace");
+ WARN_ON(error != -EPERM);
+ }
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_capget(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ return cap_capget(target, effective, inheritable, permitted);
+}
+
+static int apparmor_capset_check(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ return cap_capset_check(target, effective, inheritable, permitted);
+}
+
+static void apparmor_capset_set(struct task_struct *target,
+ kernel_cap_t *effective,
+ kernel_cap_t *inheritable,
+ kernel_cap_t *permitted)
+{
+ cap_capset_set(target, effective, inheritable, permitted);
+ return;
+}
+
+static int apparmor_capable(struct task_struct *tsk, int cap)
+{
+ int error;
+
+ /* cap_capable returns 0 on success, else -EPERM */
+ error = cap_capable(tsk, cap);
+
+ if (error == 0) {
+ struct aaprofile *active;
+
+ active = get_task_active_aaprofile(tsk);
+
+ if (active)
+ error = aa_capability(active, cap);
+
+ put_aaprofile(active);
+ }
+
+ return error;
+}
+
+static int apparmor_sysctl(struct ctl_table *table, int op)
+{
+ int error = 0;
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+
+ if ((op & 002) && active && !capable(CAP_SYS_ADMIN)) {
+ error = aa_audit_syscallreject(active, GFP_KERNEL,
+ "sysctl (write)");
+ WARN_ON(error != -EPERM);
+ }
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_syslog(int type)
+{
+ return cap_syslog(type);
+}
+
+static int apparmor_netlink_send(struct sock *sk, struct sk_buff *skb)
+{
+ return cap_netlink_send(sk, skb);
+}
+
+static int apparmor_netlink_recv(struct sk_buff *skb)
+{
+ return cap_netlink_recv(skb);
+}
+
+static void apparmor_bprm_apply_creds(struct linux_binprm *bprm, int unsafe)
+{
+ cap_bprm_apply_creds(bprm, unsafe);
+ return;
+}
+
+static int apparmor_bprm_set_security(struct linux_binprm *bprm)
+{
+ /* handle capability bits with setuid, etc */
+ cap_bprm_set_security(bprm);
+ /* already set based on script name */
+ if (bprm->sh_bang)
+ return 0;
+ return aa_register(bprm->file);
+}
+
+static int apparmor_sb_mount(char *dev_name, struct nameidata *nd, char *type,
+ unsigned long flags, void *data)
+{
+ int error = 0;
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+
+ if (active) {
+ error = aa_audit_syscallreject(active, GFP_KERNEL, "mount");
+ WARN_ON(error != -EPERM);
+ }
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_umount(struct vfsmount *mnt, int flags)
+{
+ int error = 0;
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+
+ if (active) {
+ error = aa_audit_syscallreject(active, GFP_KERNEL, "umount");
+ WARN_ON(error != -EPERM);
+ }
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_mkdir(struct inode *inode, struct dentry *dentry,
+ int mask)
+{
+ struct aaprofile *active;
+ int error = 0;
+
+ active = get_active_aaprofile();
+
+ if (active)
+ error = aa_perm_dir(active, dentry, aa_dir_mkdir);
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_rmdir(struct inode *inode, struct dentry *dentry)
+{
+ struct aaprofile *active;
+ int error = 0;
+
+ active = get_active_aaprofile();
+
+ if (active)
+ error = aa_perm_dir(active, dentry, aa_dir_rmdir);
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_create(struct inode *inode, struct dentry *dentry,
+ int mask)
+{
+ struct aaprofile *active;
+ int error = 0;
+
+ active = get_active_aaprofile();
+
+ /* At a minimum, need write perm to create */
+ if (active)
+ error = aa_perm_dentry(active, dentry, MAY_WRITE);
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_link(struct dentry *old_dentry, struct inode *inode,
+ struct dentry *new_dentry)
+{
+ int error = 0;
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+
+ if (active)
+ error = aa_link(active, new_dentry, old_dentry);
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_unlink(struct inode *inode, struct dentry *dentry)
+{
+ struct aaprofile *active;
+ int error = 0;
+
+ active = get_active_aaprofile();
+
+ if (active)
+ error = aa_perm_dentry(active, dentry, MAY_WRITE);
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_mknod(struct inode *inode, struct dentry *dentry,
+ int mode, dev_t dev)
+{
+ struct aaprofile *active;
+ int error = 0;
+
+ active = get_active_aaprofile();
+
+ if (active)
+ error = aa_perm_dentry(active, dentry, MAY_WRITE);
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_rename(struct inode *old_inode,
+ struct dentry *old_dentry,
+ struct inode *new_inode,
+ struct dentry *new_dentry)
+{
+ struct aaprofile *active;
+ int error = 0;
+
+ active = get_active_aaprofile();
+
+ if (active) {
+ error = aa_perm_dentry(active, old_dentry, MAY_READ |
+ MAY_WRITE);
+
+ if (!error)
+ error = aa_perm_dentry(active, new_dentry,
+ MAY_WRITE);
+ }
+
+ put_aaprofile(active);
+
+ return error;
+}
+
+static int apparmor_inode_permission(struct inode *inode, int mask,
+ struct nameidata *nd)
+{
+ int error = 0;
+
+ /* Do not perform check on pipes or sockets
+ * Same as apparmor_file_permission
+ */
+ if (VALID_FSTYPE(inode)) {
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+ if (active)
+ error = aa_perm_nameidata(active, nd, mask);
+ put_aaprofile(active);
+ }
+
+ return error;
+}
+
+static int apparmor_inode_setattr(struct dentry *dentry, struct iattr *iattr)
+{
+ int error = 0;
+
+ if (VALID_FSTYPE(dentry->d_inode)) {
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+ /*
+ * Mediate any attempt to change attributes of a file
+ * (chmod, chown, chgrp, etc)
+ */
+ if (active)
+ error = aa_attr(active, dentry, iattr);
+
+ put_aaprofile(active);
+ }
+
+ return error;
+}
+
+static int apparmor_inode_setxattr(struct dentry *dentry, char *name,
+ void *value, size_t size, int flags)
+{
+ int error = 0;
+
+ if (VALID_FSTYPE(dentry->d_inode)) {
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+ if (active)
+ error = aa_xattr(active, dentry, name, aa_xattr_set);
+ put_aaprofile(active);
+ }
+
+ return error;
+}
+
+static int apparmor_inode_getxattr(struct dentry *dentry, char *name)
+{
+ int error = 0;
+
+ if (VALID_FSTYPE(dentry->d_inode)) {
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+ if (active)
+ error = aa_xattr(active, dentry, name, aa_xattr_get);
+ put_aaprofile(active);
+ }
+
+ return error;
+}
+static int apparmor_inode_listxattr(struct dentry *dentry)
+{
+ int error = 0;
+
+ if (VALID_FSTYPE(dentry->d_inode)) {
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+ if (active)
+ error = aa_xattr(active, dentry, NULL, aa_xattr_list);
+ put_aaprofile(active);
+ }
+
+ return error;
+}
+
+static int apparmor_inode_removexattr(struct dentry *dentry, char *name)
+{
+ int error = 0;
+
+ if (VALID_FSTYPE(dentry->d_inode)) {
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+ if (active)
+ error = aa_xattr(active, dentry, name,
+ aa_xattr_remove);
+ put_aaprofile(active);
+ }
+
+ return error;
+}
+
+static int apparmor_file_permission(struct file *file, int mask)
+{
+ struct aaprofile *active;
+ struct aaprofile *f_profile;
+ int error = 0;
+
+ f_profile = AA_PROFILE(file->f_security);
+ /* bail out early if this isn't a mediated file */
+ if (!(f_profile && VALID_FSTYPE(file->f_dentry->d_inode)))
+ goto out;
+
+ active = get_active_aaprofile();
+ if (active && f_profile != active)
+ error = aa_perm(active, file->f_dentry, file->f_vfsmnt,
+ mask & (MAY_EXEC | MAY_WRITE | MAY_READ));
+ put_aaprofile(active);
+
+out:
+ return error;
+}
+
+static int apparmor_file_alloc_security(struct file *file)
+{
+ struct aaprofile *active;
+
+ active = get_active_aaprofile();
+ file->f_security = get_aaprofile(active);
+ put_aaprofile(active);
+
+ return 0;
+}
+
+static void apparmor_file_free_security(struct file *file)
+{
+ struct aaprofile *p = AA_PROFILE(file->f_security);
+ put_aaprofile(p);
+}
+
+static int apparmor_file_mmap(struct file *file, unsigned long reqprot,
+ unsigned long prot, unsigned long flags)
+{
+ int error = 0, mask = 0;
+ struct aaprofile *active;
+
+ if (!file)
+ goto out;
+
+ active = get_active_aaprofile();
+
+ if (prot & PROT_READ)
+ mask |= MAY_READ;
+ /* Private mappings don't require write perms since they don't
+ * write back to the files */
+ if (prot & PROT_WRITE && !(flags & MAP_PRIVATE))
+ mask |= MAY_WRITE;
+ if (prot & PROT_EXEC)
+ mask |= MAY_EXEC;
+
+ AA_DEBUG("%s: 0x%x\n", __FUNCTION__, mask);
+
+ error = aa_perm(active, file->f_dentry, file->f_vfsmnt, mask);
+
+ put_aaprofile(active);
+
+out:
+ return error;
+}
+
+static int apparmor_task_alloc_security(struct task_struct *p)
+{
+ return aa_fork(p);
+}
+
+static void apparmor_task_free_security(struct task_struct *p)
+{
+ aa_release(p);
+}
+
+static int apparmor_task_post_setuid(uid_t id0, uid_t id1, uid_t id2,
+ int flags)
+{
+ return cap_task_post_setuid(id0, id1, id2, flags);
+}
+
+static void apparmor_task_reparent_to_init(struct task_struct *p)
+{
+ cap_task_reparent_to_init(p);
+ return;
+}
+
+static int apparmor_getprocattr(struct task_struct *p, char *name, void *value,
+ size_t size)
+{
+ int error;
+ struct aaprofile *active;
+ char *str = value;
+
+ /* Subdomain only supports the "current" process attribute */
+ if (strcmp(name, "current") != 0) {
+ error = -EINVAL;
+ goto out;
+ }
+
+ if (!size) {
+ error = -ERANGE;
+ goto out;
+ }
+
+ /* must be task querying itself or admin */
+ if (current != p && !capable(CAP_SYS_ADMIN)) {
+ error = -EPERM;
+ goto out;
+ }
+
+ active = get_task_active_aaprofile(p);
+ error = aa_getprocattr(active, str, size);
+ put_aaprofile(active);
+
+out:
+ return error;
+}
+
+static int apparmor_setprocattr(struct task_struct *p, char *name, void *value,
+ size_t size)
+{
+ const char *cmd_changehat = "changehat ",
+ *cmd_setprofile = "setprofile ";
+
+ int error = -EACCES; /* default to a perm denied */
+ char *cmd = (char *)value;
+
+ /* only support messages to current */
+ if (strcmp(name, "current") != 0) {
+ error = -EINVAL;
+ goto out;
+ }
+
+ if (!size) {
+ error = -ERANGE;
+ goto out;
+ }
+
+ /* CHANGE HAT -- switch task into a subhat (subprofile) if defined */
+ if (size > strlen(cmd_changehat) &&
+ strncmp(cmd, cmd_changehat, strlen(cmd_changehat)) == 0) {
+ char *hatinfo = cmd + strlen(cmd_changehat);
+ size_t infosize = size - strlen(cmd_changehat);
+
+ /* Only the current process may change it's hat */
+ if (current != p) {
+ AA_WARN("%s: Attempt by foreign task %s(%d) "
+ "[user %d] to changehat of task %s(%d)\n",
+ __FUNCTION__,
+ current->comm,
+ current->pid,
+ current->uid,
+ p->comm,
+ p->pid);
+
+ error = -EACCES;
+ goto out;
+ }
+
+ error = aa_setprocattr_changehat(hatinfo, infosize);
+ if (error == 0)
+ /* success, set return to #bytes in orig request */
+ error = size;
+
+ /* SET NEW PROFILE */
+ } else if (size > strlen(cmd_setprofile) &&
+ strncmp(cmd, cmd_setprofile, strlen(cmd_setprofile)) == 0) {
+ struct aaprofile *active;
+
+ /* only an unconfined process with admin capabilities
+ * may change the profile of another task
+ */
+
+ if (!capable(CAP_SYS_ADMIN)) {
+ AA_WARN("%s: Unprivileged attempt by task %s(%d) "
+ "[user %d] to assign profile to task %s(%d)\n",
+ __FUNCTION__,
+ current->comm,
+ current->pid,
+ current->uid,
+ p->comm,
+ p->pid);
+ error = -EACCES;
+ goto out;
+ }
+
+ active = get_active_aaprofile();
+ if (!active) {
+ char *profile = cmd + strlen(cmd_setprofile);
+ size_t profilesize = size - strlen(cmd_setprofile);
+
+ error = aa_setprocattr_setprofile(p, profile, profilesize);
+ if (error == 0)
+ /* success,
+ * set return to #bytes in orig request
+ */
+ error = size;
+ } else {
+ AA_WARN("%s: Attempt by confined task %s(%d) "
+ "[user %d] to assign profile to task %s(%d)\n",
+ __FUNCTION__,
+ current->comm,
+ current->pid,
+ current->uid,
+ p->comm,
+ p->pid);
+
+ error = -EACCES;
+ }
+ put_aaprofile(active);
+ } else {
+ /* unknown operation */
+ AA_WARN("%s: Unknown setprocattr command '%.*s' by task %s(%d) "
+ "[user %d] for task %s(%d)\n",
+ __FUNCTION__,
+ size < 16 ? (int)size : 16,
+ cmd,
+ current->comm,
+ current->pid,
+ current->uid,
+ p->comm,
+ p->pid);
+
+ error = -EINVAL;
+ }
+
+out:
+ return error;
+}
+
+struct security_operations apparmor_ops = {
+ .ptrace = apparmor_ptrace,
+ .capget = apparmor_capget,
+ .capset_check = apparmor_capset_check,
+ .capset_set = apparmor_capset_set,
+ .sysctl = apparmor_sysctl,
+ .capable = apparmor_capable,
+ .syslog = apparmor_syslog,
+
+ .netlink_send = apparmor_netlink_send,
+ .netlink_recv = apparmor_netlink_recv,
+
+ .bprm_apply_creds = apparmor_bprm_apply_creds,
+ .bprm_set_security = apparmor_bprm_set_security,
+
+ .sb_mount = apparmor_sb_mount,
+ .sb_umount = apparmor_umount,
+
+ .inode_mkdir = apparmor_inode_mkdir,
+ .inode_rmdir = apparmor_inode_rmdir,
+ .inode_create = apparmor_inode_create,
+ .inode_link = apparmor_inode_link,
+ .inode_unlink = apparmor_inode_unlink,
+ .inode_mknod = apparmor_inode_mknod,
+ .inode_rename = apparmor_inode_rename,
+ .inode_permission = apparmor_inode_permission,
+ .inode_setattr = apparmor_inode_setattr,
+ .inode_setxattr = apparmor_inode_setxattr,
+ .inode_getxattr = apparmor_inode_getxattr,
+ .inode_listxattr = apparmor_inode_listxattr,
+ .inode_removexattr = apparmor_inode_removexattr,
+ .file_permission = apparmor_file_permission,
+ .file_alloc_security = apparmor_file_alloc_security,
+ .file_free_security = apparmor_file_free_security,
+ .file_mmap = apparmor_file_mmap,
+
+ .task_alloc_security = apparmor_task_alloc_security,
+ .task_free_security = apparmor_task_free_security,
+ .task_post_setuid = apparmor_task_post_setuid,
+ .task_reparent_to_init = apparmor_task_reparent_to_init,
+
+ .getprocattr = apparmor_getprocattr,
+ .setprocattr = apparmor_setprocattr,
+};
+
+static int __init apparmor_init(void)
+{
+ int error;
+ const char *complainmsg = ": complainmode enabled";
+
+ if ((error = create_apparmorfs())) {
+ AA_ERROR("Unable to activate AppArmor filesystem\n");
+ goto createfs_out;
+ }
+
+ if ((error = alloc_null_complain_profile())){
+ AA_ERROR("Unable to allocate null complain profile\n");
+ goto alloc_out;
+ }
+
+ if ((error = register_security(&apparmor_ops))) {
+ AA_ERROR("Unable to load AppArmor\n");
+ goto register_security_out;
+ }
+
+ AA_INFO("AppArmor initialized%s\n",
+ apparmor_complain ? complainmsg : "");
+ aa_audit_message(NULL, GFP_KERNEL, 0,
+ "AppArmor initialized%s\n",
+ apparmor_complain ? complainmsg : "");
+
+ return error;
+
+register_security_out:
+ free_null_complain_profile();
+
+alloc_out:
+ (void)destroy_apparmorfs();
+
+createfs_out:
+ return error;
+
+}
+
+static int apparmor_exit_removeall_iter(struct subdomain *sd, void *cookie)
+{
+ /* spin_lock(&sd_lock) held here */
+
+ if (__aa_is_confined(sd)) {
+ AA_DEBUG("%s: Dropping profiles %s(%d) "
+ "profile %s(%p) active %s(%p)\n",
+ __FUNCTION__,
+ sd->task->comm, sd->task->pid,
+ BASE_PROFILE(sd->active)->name,
+ BASE_PROFILE(sd->active),
+ sd->active->name, sd->active);
+ aa_switch_unconfined(sd);
+ }
+
+ return 0;
+}
+
+static void __exit apparmor_exit(void)
+{
+ unsigned long flags;
+
+ /* Remove profiles from the global profile list.
+ * This is just for tidyness as there is no way to reference this
+ * list once the AppArmor lsm hooks are detached (below)
+ */
+ aa_profilelist_release();
+
+ /* Remove profiles from active tasks
+ * If this is not done, if module is reloaded after being removed,
+ * old profiles (still refcounted in memory) will become 'magically'
+ * reattached
+ */
+
+ spin_lock_irqsave(&sd_lock, flags);
+ aa_subdomainlist_iterate(apparmor_exit_removeall_iter, NULL);
+ spin_unlock_irqrestore(&sd_lock, flags);
+
+ /* Free up list of active subdomain */
+ aa_subdomainlist_release();
+
+ free_null_complain_profile();
+
+ destroy_apparmorfs();
+
+ if (unregister_security(&apparmor_ops))
+ AA_WARN("Unable to properly unregister AppArmor\n");
+
+ /* delay for an rcu cycle to make ensure that profiles pending
+ * destruction in the rcu callback are freed.
+ */
+ synchronize_rcu();
+
+ AA_INFO("AppArmor protection removed\n");
+ aa_audit_message(NULL, GFP_KERNEL, 0,
+ "AppArmor protection removed\n");
+}
+
+security_initcall(apparmor_init);
+module_exit(apparmor_exit);
+
+MODULE_DESCRIPTION("AppArmor process confinement");
+MODULE_AUTHOR("Tony Jones <tonyj@suse.de>");
+MODULE_LICENSE("GPL");
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,472 @@
This patch implements the AppArmor file structure underneath securityfs.
Securityfs is normally mounted as /sys/kernel/security
The following files are created under /sys/kernel/security/apparmor
control
audit - Controls the global setting for auditing all
accesses.
complain - Controls the global setting for learning mode
(usually this is set per profile rather than
globally)
debug - Controls whether debugging is enabled.
This needs to be made more fine grained
logsyscall - Controls whether when logging to the audit
subsystem full syscall auditing is enabled.
The values by default for all of the above are 0.
matching - Returns the features of the installed matching submodule
profiles - Returns the profiles currently loaded and for each whether
it is in complain (learning) or enforce mode.
.load
.remove
.replace - Used by userspace tools to load, remove and replace new
profiles.
Signed-off-by: Tony Jones <tonyj@suse.de>
---
security/apparmor/apparmorfs.c | 432 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 432 insertions(+)
--- security/apparmor/apparmorfs.c.orig
+++ security/apparmor/apparmorfs.c
@@ -0,0 +1,432 @@
+/*
+ * Copyright (C) 2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * AppArmor filesystem (part of securityfs)
+ */
+
+#include <linux/security.h>
+#include <linux/vmalloc.h>
+#include <linux/module.h>
+#include <linux/seq_file.h>
+#include <asm/uaccess.h>
+
+#include "apparmor.h"
+#include "inline.h"
+#include "match/match.h"
+
+#define SECFS_AA "apparmor"
+static struct dentry *aafs_dentry = NULL;
+
+/* profile */
+extern struct seq_operations apparmorfs_profiles_op;
+static int aa_prof_open(struct inode *inode, struct file *file);
+static int aa_prof_release(struct inode *inode, struct file *file);
+
+static struct file_operations apparmorfs_profiles_fops = {
+ .open = aa_prof_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = aa_prof_release,
+};
+
+/* matching */
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos);
+
+static struct file_operations apparmorfs_matching_fops = {
+ .read = aa_matching_read,
+};
+
+
+/* interface */
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos);
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos);
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos);
+
+static struct file_operations apparmorfs_profile_load = {
+ .write = aa_profile_load
+};
+
+static struct file_operations apparmorfs_profile_replace = {
+ .write = aa_profile_replace
+};
+
+static struct file_operations apparmorfs_profile_remove = {
+ .write = aa_profile_remove
+};
+
+
+/* control */
+static u64 aa_control_get(void *data);
+static void aa_control_set(void *data, u64 val);
+
+DEFINE_SIMPLE_ATTRIBUTE(apparmorfs_control_fops, aa_control_get,
+ aa_control_set, "%lld\n");
+
+
+
+/* table of static entries */
+
+static struct root_entry {
+ const char *name;
+ int mode;
+ int access;
+ struct file_operations *fops;
+ void *data;
+
+ /* internal fields */
+ struct dentry *dentry;
+ int parent_index;
+} root_entries[] = {
+ /* our root, normally /sys/kernel/security/apparmor */
+ {SECFS_AA, S_IFDIR, 0550}, /* DO NOT EDIT/MOVE */
+
+ /* interface for obtaining list of profiles currently loaded */
+ {"profiles", S_IFREG, 0440, &apparmorfs_profiles_fops,
+ NULL},
+
+ /* interface for obtaining matching features supported */
+ {"matching", S_IFREG, 0440, &apparmorfs_matching_fops,
+ NULL},
+
+ /* interface for loading/removing/replacing profiles */
+ {".load", S_IFREG, 0640, &apparmorfs_profile_load,
+ NULL},
+ {".replace", S_IFREG, 0640, &apparmorfs_profile_replace,
+ NULL},
+ {".remove", S_IFREG, 0640, &apparmorfs_profile_remove,
+ NULL},
+
+ /* interface for setting binary config values */
+ {"control", S_IFDIR, 0550},
+ {"complain", S_IFREG, 0640, &apparmorfs_control_fops,
+ &apparmor_complain},
+ {"audit", S_IFREG, 0640, &apparmorfs_control_fops,
+ &apparmor_audit},
+ {"debug", S_IFREG, 0640, &apparmorfs_control_fops,
+ &apparmor_debug},
+ {"logsyscall", S_IFREG, 0640, &apparmorfs_control_fops,
+ &apparmor_logsyscall},
+ {NULL, S_IFDIR, 0},
+
+ /* root end */
+ {NULL, S_IFDIR, 0}
+};
+
+#define AAFS_DENTRY root_entries[0].dentry
+
+static const unsigned int num_entries =
+ sizeof(root_entries) / sizeof(struct root_entry);
+
+
+
+static int aa_prof_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &apparmorfs_profiles_op);
+}
+
+
+static int aa_prof_release(struct inode *inode, struct file *file)
+{
+ return seq_release(inode, file);
+}
+
+static ssize_t aa_matching_read(struct file *file, char __user *buf,
+ size_t size, loff_t *ppos)
+{
+ const char *matching = aamatch_features();
+
+ return simple_read_from_buffer(buf, size, ppos, matching,
+ strlen(matching));
+}
+
+static char *aa_simple_write_to_buffer(const char __user *userbuf,
+ size_t alloc_size, size_t copy_size,
+ loff_t *pos, const char *msg)
+{
+ struct aaprofile *active;
+ char *data;
+
+ if (*pos != 0) {
+ /* only writes from pos 0, that is complete writes */
+ data = ERR_PTR(-ESPIPE);
+ goto out;
+ }
+
+ /* Don't allow confined processes to load/replace/remove profiles.
+ * No sane person would add rules allowing this to a profile
+ * but we enforce the restriction anyways.
+ */
+ rcu_read_lock();
+ active = get_activeptr_rcu();
+ if (active) {
+ AA_WARN("REJECTING access to profile %s (%s(%d) "
+ "profile %s active %s)\n",
+ msg, current->comm, current->pid,
+ BASE_PROFILE(active)->name, active->name);
+
+ data = ERR_PTR(-EPERM);
+ goto out;
+ }
+ rcu_read_unlock();
+
+ data = vmalloc(alloc_size);
+ if (data == NULL) {
+ data = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ if (copy_from_user(data, userbuf, copy_size)) {
+ vfree(data);
+ data = ERR_PTR(-EFAULT);
+ goto out;
+ }
+
+out:
+ return data;
+}
+
+static ssize_t aa_profile_load(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ char *data;
+ ssize_t error;
+
+ data = aa_simple_write_to_buffer(buf, size, size, pos, "load");
+
+ if (!IS_ERR(data)) {
+ error = aa_file_prof_add(data, size);
+ vfree(data);
+ } else {
+ error = PTR_ERR(data);
+ }
+
+ return error;
+}
+
+static ssize_t aa_profile_replace(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ char *data;
+ ssize_t error;
+
+ data = aa_simple_write_to_buffer(buf, size, size, pos, "replacement");
+
+ if (!IS_ERR(data)) {
+ error = aa_file_prof_repl(data, size);
+ vfree(data);
+ } else {
+ error = PTR_ERR(data);
+ }
+
+ return error;
+}
+
+static ssize_t aa_profile_remove(struct file *f, const char __user *buf,
+ size_t size, loff_t *pos)
+{
+ char *data;
+ ssize_t error;
+
+ /* aa_file_prof_remove needs a null terminated string so 1 extra
+ * byte is allocated and null the copied data is then null terminated
+ */
+ data = aa_simple_write_to_buffer(buf, size+1, size, pos, "removal");
+
+ if (!IS_ERR(data)) {
+ data[size] = 0;
+ error = aa_file_prof_remove(data, size);
+ vfree(data);
+ } else {
+ error = PTR_ERR(data);
+ }
+
+ return error;
+}
+
+static u64 aa_control_get(void *data)
+{
+ return *(int *)data;
+}
+
+static void aa_control_set(void *data, u64 val)
+{
+ if (val > 1)
+ val = 1;
+
+ *(int*)data = (int)val;
+}
+
+static void clear_apparmorfs(void)
+{
+ unsigned int i;
+
+ for (i=0; i < num_entries;i++) {
+ unsigned int index;
+
+ if (root_entries[i].mode == S_IFDIR) {
+ if (root_entries[i].name)
+ /* defer dir free till all sub-entries freed */
+ continue;
+ else
+ /* cleanup parent */
+ index = root_entries[i].parent_index;
+ } else {
+ index = i;
+ }
+
+ if (root_entries[index].dentry) {
+ securityfs_remove(root_entries[index].dentry);
+
+ AA_DEBUG("%s: deleted apparmorfs entry name=%s "
+ "dentry=%p\n",
+ __FUNCTION__,
+ root_entries[index].name,
+ root_entries[index].dentry);
+
+ root_entries[index].dentry = NULL;
+ root_entries[index].parent_index = 0;
+ }
+ }
+}
+
+static int populate_apparmorfs(struct dentry *root)
+{
+ unsigned int i, parent_index, depth;
+
+ for (i = 0; i < num_entries; i++) {
+ root_entries[i].dentry = NULL;
+ root_entries[i].parent_index = 0;
+ }
+
+ /* 1. Verify entry 0 is valid [sanity check] */
+ if (num_entries == 0 ||
+ !root_entries[0].name ||
+ strcmp(root_entries[0].name, SECFS_AA) != 0 ||
+ root_entries[0].mode != S_IFDIR) {
+ AA_ERROR("%s: root entry 0 is not SECFS_AA/dir\n",
+ __FUNCTION__);
+ goto error;
+ }
+
+ /* 2. Build back pointers */
+ parent_index = 0;
+ depth = 1;
+
+ for (i = 1; i < num_entries; i++) {
+ root_entries[i].parent_index = parent_index;
+
+ if (root_entries[i].name &&
+ root_entries[i].mode == S_IFDIR) {
+ depth++;
+ parent_index = i;
+ } else if (!root_entries[i].name) {
+ if (root_entries[i].mode != S_IFDIR || depth == 0) {
+ AA_ERROR("%s: root_entry %d invalid (%u %d)",
+ __FUNCTION__, i,
+ root_entries[i].mode,
+ root_entries[i].parent_index);
+ goto error;
+ }
+
+ depth--;
+ parent_index = root_entries[parent_index].parent_index;
+ }
+ }
+
+ if (depth != 0) {
+ AA_ERROR("%s: root_entry table not correctly terminated\n",
+ __FUNCTION__);
+ goto error;
+ }
+
+ /* 3. Create root (parent=NULL) */
+ root_entries[0].dentry = securityfs_create_file(
+ root_entries[0].name,
+ root_entries[0].mode |
+ root_entries[0].access,
+ NULL, NULL, NULL);
+
+ if (IS_ERR(root_entries[0].dentry))
+ goto error;
+ else
+ AA_DEBUG("%s: created securityfs/apparmor [dentry=%p]\n",
+ __FUNCTION__, root_entries[0].dentry);
+
+
+ /* 4. create remaining nodes */
+ for (i = 1; i < num_entries; i++) {
+ struct dentry *parent;
+ void *data = NULL;
+ struct file_operations *fops = NULL;
+
+ /* end of directory ? */
+ if (!root_entries[i].name)
+ continue;
+
+ parent = root_entries[root_entries[i].parent_index].dentry;
+
+ if (root_entries[i].mode != S_IFDIR) {
+ data = root_entries[i].data;
+ fops = root_entries[i].fops;
+ }
+
+ root_entries[i].dentry = securityfs_create_file(
+ root_entries[i].name,
+ root_entries[i].mode |
+ root_entries[i].access,
+ parent,
+ data,
+ fops);
+
+ if (IS_ERR(root_entries[i].dentry))
+ goto cleanup_error;
+
+ AA_DEBUG("%s: added apparmorfs entry "
+ "name=%s mode=%x dentry=%p [parent %p]\n",
+ __FUNCTION__, root_entries[i].name,
+ root_entries[i].mode|root_entries[i].access,
+ root_entries[i].dentry, parent);
+ }
+
+ return 0;
+
+cleanup_error:
+ clear_apparmorfs();
+
+error:
+ return -EINVAL;
+}
+
+int create_apparmorfs(void)
+{
+ int error = 0;
+
+ if (AAFS_DENTRY) {
+ error = -EEXIST;
+ AA_ERROR("%s: Subdomain securityfs already exists\n",
+ __FUNCTION__);
+ } else {
+ error = populate_apparmorfs(aafs_dentry);
+ if (error != 0) {
+ AA_ERROR("%s: Error populating Subdomain securityfs\n",
+ __FUNCTION__);
+ }
+ }
+
+ return error;
+}
+
+void destroy_apparmorfs(void)
+{
+ if (AAFS_DENTRY)
+ clear_apparmorfs();
+}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,907 @@
This patch implements the interface between the userspace policy loader
and the kernel module. It is called by the .load, .remove and .replace
file_operations hooks implemented in apparmorfs.c.
The code is reponsible for serializing data in a platform independant
manner from userspace and creating/activating the necessary apparmor
profiles.
Certain aspects are delegated to the sub matching module which implements
the aamatch_* functions.
Signed-off-by: Tony Jones <tonyj@suse.de>
---
security/apparmor/module_interface.c | 840 +++++++++++++++++++++++++++++++++++
security/apparmor/module_interface.h | 37 +
2 files changed, 877 insertions(+)
--- security/apparmor/module_interface.c.orig
+++ security/apparmor/module_interface.c
@@ -0,0 +1,840 @@
+/*
+ * Copyright (C) 1998-2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * AppArmor userspace policy interface
+ */
+
+#include <asm/unaligned.h>
+
+#include "apparmor.h"
+#include "inline.h"
+#include "module_interface.h"
+#include "match/match.h"
+
+/* aa_code defined in module_interface.h */
+
+const int aacode_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
+
+struct aa_taskreplace_data {
+ struct aaprofile *old_profile;
+ struct aaprofile *new_profile;
+};
+
+/* inlines must be forward of there use in newer version of gcc,
+ just forward declaring with a prototype won't work anymore */
+
+static inline void free_aa_entry(struct aa_entry *entry)
+{
+ if (entry) {
+ kfree(entry->filename);
+ aamatch_free(entry->extradata);
+ kfree(entry);
+ }
+}
+
+/**
+ * alloc_aa_entry - create new empty aa_entry
+ * This routine allocates, initializes, and returns a new aa_entry
+ * file entry structure. Structure is zeroed. Returns new structure on
+ * success, %NULL on failure.
+ */
+static inline struct aa_entry *alloc_aa_entry(void)
+{
+ struct aa_entry *entry;
+
+ AA_DEBUG("%s\n", __FUNCTION__);
+ entry = kzalloc(sizeof(struct aa_entry), GFP_KERNEL);
+ if (entry) {
+ int i;
+ INIT_LIST_HEAD(&entry->list);
+ for (i = 0; i <= POS_AA_FILE_MAX; i++) {
+ INIT_LIST_HEAD(&entry->listp[i]);
+ }
+ }
+ return entry;
+}
+
+/**
+ * free_aaprofile_rcu - rcu callback for free profiles
+ * @head: rcu_head struct of the profile whose reference is being put.
+ *
+ * the rcu callback routine, which delays the freeing of a profile when
+ * its last reference is put.
+ */
+static void free_aaprofile_rcu(struct rcu_head *head)
+{
+ struct aaprofile *p = container_of(head, struct aaprofile, rcu);
+ free_aaprofile(p);
+}
+
+/**
+ * task_remove - remove profile from a task's subdomain
+ * @sd: task's subdomain
+ *
+ * remove the active profile from a task's subdomain, switching the task
+ * to an unconfined state.
+ */
+static inline void task_remove(struct subdomain *sd)
+{
+ /* spin_lock(&sd_lock) held here */
+ AA_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
+ __FUNCTION__,
+ sd->task->comm,
+ sd->task->pid,
+ BASE_PROFILE(sd->active)->name,
+ sd->active->name);
+
+ aa_switch_unconfined(sd);
+}
+
+/** taskremove_iter - Iterator to unconfine subdomains which match cookie
+ * @sd: subdomain to consider for profile removal
+ * @cookie: pointer to the oldprofile which is being removed
+ *
+ * If the subdomain's active profile matches old_profile, then call
+ * task_remove() to remove the profile leaving the task (subdomain) unconfined.
+ */
+static int taskremove_iter(struct subdomain *sd, void *cookie)
+{
+ struct aaprofile *old_profile = (struct aaprofile *)cookie;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sd_lock, flags);
+
+ if (__aa_is_confined(sd) && BASE_PROFILE(sd->active) == old_profile) {
+ task_remove(sd);
+ }
+
+ spin_unlock_irqrestore(&sd_lock, flags);
+
+ return 0;
+}
+
+/** task_replace - replace subdomain's current profile with a new profile
+ * @sd: subdomain to replace the profile on
+ * @new: new profile
+ *
+ * Replace a task's (subdomain's) active profile with a new profile. If
+ * task was in a hat then the new profile will also be in the equivalent
+ * hat in the new profile if it exists. If it doesn't exist the
+ * task will be placed in the special null_profile state.
+ */
+static inline void task_replace(struct subdomain *sd, struct aaprofile *new)
+{
+ AA_DEBUG("%s: replacing profile for task %s(%d) "
+ "profile=%s (%p) active=%s (%p)\n",
+ __FUNCTION__,
+ sd->task->comm, sd->task->pid,
+ BASE_PROFILE(sd->active)->name, BASE_PROFILE(sd->active),
+ sd->active->name, sd->active);
+
+ if (!sd->active)
+ goto out;
+
+ if (IN_SUBPROFILE(sd->active)) {
+ struct aaprofile *nactive;
+
+ /* The old profile was in a hat, check to see if the new
+ * profile has an equivalent hat */
+ nactive = __aa_find_profile(sd->active->name, &new->sub);
+
+ if (!nactive)
+ nactive = get_aaprofile(new->null_profile);
+
+ aa_switch(sd, nactive);
+ put_aaprofile(nactive);
+ } else {
+ aa_switch(sd, new);
+ }
+
+ out:
+ return;
+}
+
+/** taskreplace_iter - Iterator to replace a subdomain's profile
+ * @sd: subdomain to consider for profile replacement
+ * @cookie: pointer to the old profile which is being replaced.
+ *
+ * If the subdomain's active profile matches old_profile call
+ * task_replace() to replace with the subdomain's active profile with
+ * the new profile.
+ */
+static int taskreplace_iter(struct subdomain *sd, void *cookie)
+{
+ struct aa_taskreplace_data *data = (struct aa_taskreplace_data *)cookie;
+ unsigned long flags;
+
+ spin_lock_irqsave(&sd_lock, flags);
+
+ if (__aa_is_confined(sd) &&
+ BASE_PROFILE(sd->active) == data->old_profile)
+ task_replace(sd, data->new_profile);
+
+ spin_unlock_irqrestore(&sd_lock, flags);
+
+ return 0;
+}
+
+static inline int aa_inbounds(struct aa_ext *e, size_t size)
+{
+ return (e->pos + size <= e->end);
+}
+
+/**
+ * aaconvert - convert trailing values of serialized type codes
+ * @code: type code
+ * @dest: pointer to object to receive the converted value
+ * @src: pointer to value to convert
+ *
+ * for serialized type codes which have a trailing value, convert it
+ * and place it in @dest. If a code does not have a trailing value nop.
+ */
+static void aaconvert(enum aa_code code, void *dest, void *src)
+{
+ switch (code) {
+ case AA_U8:
+ *(u8 *)dest = *(u8 *) src;
+ break;
+ case AA_U16:
+ case AA_NAME:
+ case AA_DYN_STRING:
+ *(u16 *)dest = le16_to_cpu(get_unaligned((u16 *)src));
+ break;
+ case AA_U32:
+ case AA_STATIC_BLOB:
+ *(u32 *)dest = le32_to_cpu(get_unaligned((u32 *)src));
+ break;
+ case AA_U64:
+ *(u64 *)dest = le64_to_cpu(get_unaligned((u64 *)src));
+ break;
+ default:
+ /* nop - all other type codes do not have a trailing value */
+ ;
+ }
+}
+
+/**
+ * aa_is_X - check if the next element is of type X
+ * @e: serialized data extent information
+ * @code: type code
+ * @data: object located at @e->pos (of type @code) is written into @data
+ * if @data is non-null. if data is null it means skip this
+ * entry
+ * check to see if the next element in the serialized data stream is of type
+ * X and check that it is with in bounds, if so put the associated value in
+ * @data.
+ * return the size of bytes associated with the returned data
+ * for complex object like blob and string a pointer to the allocated
+ * data is returned in data, but the size of the blob or string is
+ * returned.
+ */
+static u32 aa_is_X(struct aa_ext *e, enum aa_code code, void *data)
+{
+ void *pos = e->pos;
+ int ret = 0;
+ if (!aa_inbounds(e, AA_CODE_BYTE + aacode_datasize[code]))
+ goto fail;
+ if (code != *(u8 *)e->pos)
+ goto out;
+ e->pos += AA_CODE_BYTE;
+ if (code == AA_NAME) {
+ u16 size;
+ /* name codes are followed by X bytes */
+ size = le16_to_cpu(get_unaligned((u16 *)e->pos));
+ if (!aa_inbounds(e, (size_t) size))
+ goto fail;
+ if (data)
+ *(u16 *)data = size;
+ e->pos += aacode_datasize[code];
+ ret = 1 + aacode_datasize[code];
+ } else if (code == AA_DYN_STRING) {
+ u16 size;
+ char *str;
+ /* strings codes are followed by X bytes */
+ size = le16_to_cpu(get_unaligned((u16 *)e->pos));
+ e->pos += aacode_datasize[code];
+ if (!aa_inbounds(e, (size_t) size))
+ goto fail;
+ if (data) {
+ * (char **)data = NULL;
+ str = kmalloc(size, GFP_KERNEL);
+ if (!str)
+ goto fail;
+ memcpy(str, e->pos, (size_t) size);
+ str[size-1] = '\0';
+ * (char **)data = str;
+ }
+ e->pos += size;
+ ret = size;
+ } else if (code == AA_STATIC_BLOB) {
+ u32 size;
+ /* blobs are followed by X bytes, that can be 2^32 */
+ size = le32_to_cpu(get_unaligned((u32 *)e->pos));
+ e->pos += aacode_datasize[code];
+ if (!aa_inbounds(e, (size_t) size))
+ goto fail;
+ if (data)
+ memcpy(data, e->pos, (size_t) size);
+ e->pos += size;
+ ret = size;
+ } else {
+ if (data)
+ aaconvert(code, data, e->pos);
+ e->pos += aacode_datasize[code];
+ ret = 1 + aacode_datasize[code];
+ }
+out:
+ return ret;
+fail:
+ e->pos = pos;
+ return 0;
+}
+
+/**
+ * aa_is_nameX - check is the next element is of type X with a name of @name
+ * @e: serialized data extent information
+ * @code: type code
+ * @data: location to store deserialized data if match isX criteria
+ * @name: name to match to the serialized element.
+ *
+ * check that the next serialized data element is of type X and has a tag
+ * name @name. If the code matches and name (if specified) matches then
+ * the packed data is unpacked into *data. (Note for strings this is the
+ * size, and the next data in the stream is the string data)
+ * returns %0 if either match failes
+ */
+static int aa_is_nameX(struct aa_ext *e, enum aa_code code, void *data,
+ const char *name)
+{
+ void *pos = e->pos;
+ u16 size;
+ u32 ret;
+ /* check for presence of a tagname, and if present name size
+ * AA_NAME tag value is a u16 */
+ if (aa_is_X(e, AA_NAME, &size)) {
+ /* if a name is specified it must match. otherwise skip tag */
+ if (name && ((strlen(name) != size-1) ||
+ strncmp(name, (char *)e->pos, (size_t)size-1)))
+ goto fail;
+ e->pos += size;
+ }
+ /* now check if data actually matches */
+ ret = aa_is_X(e, code, data);
+ if (!ret)
+ goto fail;
+ return ret;
+
+fail:
+ e->pos = pos;
+ return 0;
+}
+
+/* macro to wrap error case to make a block of reads look nicer */
+#define AA_READ_X(E, C, D, N) \
+ do { \
+ u32 __ret; \
+ __ret = aa_is_nameX((E), (C), (D), (N)); \
+ if (!__ret) \
+ goto fail; \
+ } while (0)
+
+/**
+ * aa_activate_net_entry - unpacked serialized net entries
+ * @e: serialized data extent information
+ *
+ * Ignore/skips net entries if they are present in the serialized data
+ * stream. Network confinement rules are currently unsupported but some
+ * user side tools can generate them so they are currently ignored.
+ */
+static inline int aa_activate_net_entry(struct aa_ext *e)
+{
+ AA_READ_X(e, AA_STRUCT, NULL, "ne");
+ AA_READ_X(e, AA_U32, NULL, NULL);
+ AA_READ_X(e, AA_U32, NULL, NULL);
+ AA_READ_X(e, AA_U32, NULL, NULL);
+ AA_READ_X(e, AA_U16, NULL, NULL);
+ AA_READ_X(e, AA_U16, NULL, NULL);
+ AA_READ_X(e, AA_U32, NULL, NULL);
+ AA_READ_X(e, AA_U32, NULL, NULL);
+ AA_READ_X(e, AA_U16, NULL, NULL);
+ AA_READ_X(e, AA_U16, NULL, NULL);
+ /* interface name is optional so just ignore return code */
+ aa_is_nameX(e, AA_DYN_STRING, NULL, NULL);
+ AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
+
+ return 1;
+fail:
+ return 0;
+}
+
+/**
+ * aa_activate_file_entry - unpack serialized file entry
+ * @e: serialized data extent information
+ *
+ * unpack the information used for a file ACL entry.
+ */
+static inline struct aa_entry *aa_activate_file_entry(struct aa_ext *e)
+{
+ struct aa_entry *entry = NULL;
+
+ if (!(entry = alloc_aa_entry()))
+ goto fail;
+
+ AA_READ_X(e, AA_STRUCT, NULL, "fe");
+ AA_READ_X(e, AA_DYN_STRING, &entry->filename, NULL);
+ AA_READ_X(e, AA_U32, &entry->mode, "file.mode");
+ AA_READ_X(e, AA_U32, &entry->type, "file.pattern_type");
+
+ entry->extradata = aamatch_alloc(entry->type);
+ if (IS_ERR(entry->extradata)) {
+ entry->extradata = NULL;
+ goto fail;
+ }
+
+ if (entry->extradata &&
+ aamatch_serialize(entry->extradata, e, aa_is_nameX) != 0) {
+ goto fail;
+ }
+ AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
+
+ switch (entry->type) {
+ case aa_entry_literal:
+ AA_DEBUG("%s: %s [no pattern] mode=0x%x\n",
+ __FUNCTION__,
+ entry->filename,
+ entry->mode);
+ break;
+ case aa_entry_tailglob:
+ AA_DEBUG("%s: %s [tailglob] mode=0x%x\n",
+ __FUNCTION__,
+ entry->filename,
+ entry->mode);
+ break;
+ case aa_entry_pattern:
+ AA_DEBUG("%s: %s mode=0x%x\n",
+ __FUNCTION__,
+ entry->filename,
+ entry->mode);
+ break;
+ default:
+ AA_WARN("%s: INVALID entry_match_type %d\n",
+ __FUNCTION__,
+ (int)entry->type);
+ goto fail;
+ }
+
+ return entry;
+
+fail:
+ aamatch_free(entry->extradata);
+ free_aa_entry(entry);
+ return NULL;
+}
+
+/**
+ * check_rule_and_add - check a file rule is valid and add to a profile
+ * @file_entry: file rule to add
+ * @profile: profile to add the rule to
+ * @message: error message returned if the addition failes.
+ *
+ * perform consistency check to ensure that a file rule entry is valid.
+ * If the rule is valid it is added to the profile.
+ */
+static inline int check_rule_and_add(struct aa_entry *file_entry,
+ struct aaprofile *profile,
+ const char **message)
+{
+ /* verify consistency of x, px, ix, ux for entry against
+ possible duplicates for this entry */
+ int mode = AA_EXEC_MODIFIER_MASK(file_entry->mode);
+ int i;
+
+ if (mode && !(AA_MAY_EXEC & file_entry->mode)) {
+ *message = "inconsistent rule, x modifiers without x";
+ goto out;
+ }
+
+ /* check that only 1 of the modifiers is set */
+ if (mode && (mode & (mode - 1))) {
+ *message = "inconsistent rule, multiple x modifiers";
+ goto out;
+ }
+
+ list_add(&file_entry->list, &profile->file_entry);
+ profile->num_file_entries++;
+
+ mode = file_entry->mode;
+
+ /* Handle partitioned lists
+ * Chain entries onto sublists based on individual
+ * permission bits. This allows more rapid searching.
+ */
+ for (i = 0; i <= POS_AA_FILE_MAX; i++) {
+ if (mode & (1 << i))
+ /* profile->file_entryp[i] initially set to
+ * NULL in alloc_aaprofile() */
+ list_add(&file_entry->listp[i],
+ &profile->file_entryp[i]);
+ }
+
+ return 1;
+
+out:
+ free_aa_entry(file_entry);
+ return 0;
+}
+
+#define AA_ENTRY_LIST(NAME) \
+ do { \
+ if (aa_is_nameX(e, AA_LIST, NULL, (NAME))) { \
+ rulename = ""; \
+ error_string = "Invalid file entry"; \
+ while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) { \
+ struct aa_entry *file_entry; \
+ file_entry = aa_activate_file_entry(e); \
+ if (!file_entry) \
+ goto fail; \
+ if (!check_rule_and_add(file_entry, profile, \
+ &error_string)) { \
+ rulename = file_entry->filename; \
+ goto fail; \
+ } \
+ } \
+ } \
+ } while (0)
+
+/**
+ * aa_activate_profile - unpack a serialized profile
+ * @e: serialized data extent information
+ * @error: error code returned if unpacking fails
+ */
+static struct aaprofile *aa_activate_profile(struct aa_ext *e, ssize_t *error)
+{
+ struct aaprofile *profile = NULL;
+ const char *rulename = "";
+ const char *error_string = "Invalid Profile";
+
+ *error = -EPROTO;
+
+ profile = alloc_aaprofile();
+ if (!profile) {
+ error_string = "Could not allocate profile";
+ *error = -ENOMEM;
+ goto fail;
+ }
+
+ /* check that we have the right struct being passed */
+ AA_READ_X(e, AA_STRUCT, NULL, "profile");
+ AA_READ_X(e, AA_DYN_STRING, &profile->name, NULL);
+
+ error_string = "Invalid flags";
+ /* per profile debug flags (debug, complain, audit) */
+ AA_READ_X(e, AA_STRUCT, NULL, "flags");
+ AA_READ_X(e, AA_U32, &(profile->flags.debug), "profile.flags.debug");
+ AA_READ_X(e, AA_U32, &(profile->flags.complain),
+ "profile.flags.complain");
+ AA_READ_X(e, AA_U32, &(profile->flags.audit), "profile.flags.audit");
+ AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
+
+ error_string = "Invalid capabilities";
+ AA_READ_X(e, AA_U32, &(profile->capabilities), "profile.capabilities");
+
+ /* get the file entries. */
+ AA_ENTRY_LIST("pgent"); /* pcre rules */
+ AA_ENTRY_LIST("sgent"); /* simple globs */
+ AA_ENTRY_LIST("fent"); /* regular file entries */
+
+ /* get the net entries */
+ if (aa_is_nameX(e, AA_LIST, NULL, "net")) {
+ error_string = "Invalid net entry";
+ while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) {
+ if (!aa_activate_net_entry(e))
+ goto fail;
+ }
+ }
+ rulename = "";
+
+ /* get subprofiles */
+ if (aa_is_nameX(e, AA_LIST, NULL, "hats")) {
+ error_string = "Invalid profile hat";
+ while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) {
+ struct aaprofile *subprofile;
+ subprofile = aa_activate_profile(e, error);
+ if (!subprofile)
+ goto fail;
+ subprofile->parent = profile;
+ list_add(&subprofile->list, &profile->sub);
+ }
+ }
+
+ error_string = "Invalid end of profile";
+ AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
+
+ return profile;
+
+fail:
+ AA_WARN("%s: %s %s in profile %s\n", INTERFACE_ID, rulename,
+ error_string, profile && profile->name ? profile->name
+ : "unknown");
+
+ if (profile) {
+ free_aaprofile(profile);
+ profile = NULL;
+ }
+
+ return NULL;
+}
+
+/**
+ * aa_activate_top_profile - unpack a serialized base profile
+ * @e: serialized data extent information
+ * @error: error code returned if unpacking fails
+ *
+ * check interface version unpack a profile and all its hats and patch
+ * in any extra information that the profile needs.
+ */
+static void *aa_activate_top_profile(struct aa_ext *e, ssize_t *error)
+{
+ struct aaprofile *profile = NULL;
+
+ /* get the interface version */
+ if (!aa_is_nameX(e, AA_U32, &e->version, "version")) {
+ AA_WARN("%s: version missing\n", INTERFACE_ID);
+ *error = -EPROTONOSUPPORT;
+ goto fail;
+ }
+
+ /* check that the interface version is currently supported */
+ if (e->version != 2) {
+ AA_WARN("%s: unsupported interface version (%d)\n",
+ INTERFACE_ID, e->version);
+ *error = -EPROTONOSUPPORT;
+ goto fail;
+ }
+
+ profile = aa_activate_profile(e, error);
+ if (!profile)
+ goto fail;
+
+ if (!list_empty(&profile->sub) || profile->flags.complain) {
+ if (attach_nullprofile(profile))
+ goto fail;
+ }
+ return profile;
+
+fail:
+ free_aaprofile(profile);
+ return NULL;
+}
+
+/**
+ * aa_file_prof_add - add a new profile to the profile list
+ * @data: serialized data stream
+ * @size: size of the serialized data stream
+ *
+ * unpack and add a profile to the profile list. Return %0 or error
+ */
+ssize_t aa_file_prof_add(void *data, size_t size)
+{
+ struct aaprofile *profile = NULL;
+
+ struct aa_ext e = {
+ .start = data,
+ .end = data + size,
+ .pos = data
+ };
+ ssize_t error;
+
+ profile = aa_activate_top_profile(&e, &error);
+ if (!profile) {
+ AA_DEBUG("couldn't activate profile\n");
+ goto out;
+ }
+
+ /* aa_activate_top_profile allocates profile with initial 1 count
+ * aa_profilelist_add transfers that ref to profile list without
+ * further incrementing
+ */
+ if (aa_profilelist_add(profile)) {
+ error = size;
+ } else {
+ AA_WARN("trying to add profile (%s) that already exists.\n",
+ profile->name);
+ put_aaprofile(profile);
+ error = -EEXIST;
+ }
+
+out:
+ return error;
+}
+
+/**
+ * aa_file_prof_repl - replace a profile on the profile list
+ * @udata: serialized data stream
+ * @size: size of the serialized data stream
+ *
+ * unpack and replace a profile on the profile list and uses of that profile
+ * by any subdomain. If the profile does not exist on the profile list
+ * it is added. Return %0 or error.
+ */
+ssize_t aa_file_prof_repl(void *udata, size_t size)
+{
+ struct aa_taskreplace_data data;
+ struct aa_ext e = {
+ .start = udata,
+ .end = udata + size,
+ .pos = udata
+ };
+
+ ssize_t error;
+
+ data.new_profile = aa_activate_top_profile(&e, &error);
+ if (!data.new_profile) {
+ AA_DEBUG("couldn't activate profile\n");
+ goto out;
+ }
+
+ /* Refcount on data.new_profile is 1 (aa_activate_top_profile).
+ *
+ * This reference will be inherited by aa_profilelist_replace for it's
+ * profile list reference but this isn't sufficient.
+ *
+ * Another replace (*for-same-profile*) may race us here.
+ * Task A calls aa_profilelist_replace(new_profile) and is interrupted.
+ * Task B old_profile = aa_profilelist_replace() will return task A's
+ * new_profile with the count of 1. If task B proceeeds to put this
+ * profile it will dissapear from under task A.
+ *
+ * Grab extra reference on new_profile to prevent this
+ */
+
+ get_aaprofile(data.new_profile);
+
+ data.old_profile = aa_profilelist_replace(data.new_profile);
+
+ /* If there was an old profile, find all currently executing tasks
+ * using this profile and replace the old profile with the new.
+ */
+ if (data.old_profile) {
+ AA_DEBUG("%s: try to replace profile (%p)%s\n",
+ __FUNCTION__,
+ data.old_profile,
+ data.old_profile->name);
+
+ aa_subdomainlist_iterate(taskreplace_iter, (void *)&data);
+
+ /* it's off global list, and we are done replacing */
+ put_aaprofile(data.old_profile);
+ }
+
+ /* release extra reference obtained above (race) */
+ put_aaprofile(data.new_profile);
+
+ error = size;
+
+out:
+ return error;
+}
+
+/**
+ * aa_file_prof_remove - remove a profile from the system
+ * @name: name of the profile to remove
+ * @size: size of the name
+ *
+ * remove a profile from the profile list and all subdomain references
+ * to said profile. Return %0 on success, else error.
+ */
+ssize_t aa_file_prof_remove(const char *name, size_t size)
+{
+ struct aaprofile *old_profile;
+
+ /* if the old profile exists it will be removed from the list and
+ * a reference is returned.
+ */
+ old_profile = aa_profilelist_remove(name);
+
+ if (old_profile) {
+ /* remove profile from any tasks using it */
+ aa_subdomainlist_iterate(taskremove_iter, (void *)old_profile);
+
+ /* drop reference obtained by aa_profilelist_remove */
+ put_aaprofile(old_profile);
+ } else {
+ AA_WARN("%s: trying to remove profile (%s) that "
+ "doesn't exist - skipping.\n", __FUNCTION__, name);
+ return -ENOENT;
+ }
+
+ return size;
+}
+
+/**
+ * free_aaprofile_kref - free aaprofile by kref (called by put_aaprofile)
+ * @kr: kref callback for freeing of a profile
+ */
+void free_aaprofile_kref(struct kref *kr)
+{
+ struct aaprofile *p=container_of(kr, struct aaprofile, count);
+
+ call_rcu(&p->rcu, free_aaprofile_rcu);
+}
+
+/**
+ * free_aaprofile - free aaprofile structure
+ * @profile: the profile to free
+ *
+ * free a profile, its file entries hats and null_profile. All references
+ * to the profile, its hats and null_profile must have been put.
+ * If the profile was referenced by a subdomain free_aaprofile should be
+ * called from an rcu callback routine.
+ */
+void free_aaprofile(struct aaprofile *profile)
+{
+ struct aa_entry *ent, *tmp;
+ struct aaprofile *p, *ptmp;
+
+ AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
+
+ if (!profile)
+ return;
+
+ /* profile is still on global profile list -- invalid */
+ if (!list_empty(&profile->list)) {
+ AA_ERROR("%s: internal error, "
+ "profile '%s' still on global list\n",
+ __FUNCTION__,
+ profile->name);
+ BUG();
+ }
+
+ list_for_each_entry_safe(ent, tmp, &profile->file_entry, list) {
+ if (ent->filename)
+ AA_DEBUG("freeing aa_entry: %p %s\n",
+ ent->filename, ent->filename);
+ list_del_init(&ent->list);
+ free_aa_entry(ent);
+ }
+
+ /* use free_aaprofile instead of put_aaprofile to destroy the
+ * null_profile, because the null_profile use the same reference
+ * counting as hats, ie. the count goes to the base profile.
+ */
+ free_aaprofile(profile->null_profile);
+ list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
+ list_del_init(&p->list);
+ p->parent = NULL;
+ put_aaprofile(p);
+ }
+
+ if (profile->name) {
+ AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
+ kfree(profile->name);
+ }
+
+ kfree(profile);
+}
--- security/apparmor/module_interface.h.orig
+++ security/apparmor/module_interface.h
@@ -0,0 +1,37 @@
+#ifndef __MODULEINTERFACE_H
+#define __MODULEINTERFACE_H
+
+/* Codes of the types of basic structures that are understood */
+#define AA_CODE_BYTE (sizeof(u8))
+#define INTERFACE_ID "INTERFACE"
+
+#define SUBDOMAIN_INTERFACE_VERSION 2
+
+enum aa_code {
+ AA_U8,
+ AA_U16,
+ AA_U32,
+ AA_U64,
+ AA_NAME, /* same as string except it is items name */
+ AA_DYN_STRING,
+ AA_STATIC_BLOB,
+ AA_STRUCT,
+ AA_STRUCTEND,
+ AA_LIST,
+ AA_LISTEND,
+ AA_OFFSET,
+ AA_BAD
+};
+
+/* aa_ext tracks the kernel buffer and read position in it. The interface
+ * data is copied into a kernel buffer in apparmorfs and then handed off to
+ * the activate routines.
+ */
+struct aa_ext {
+ void *start;
+ void *end;
+ void *pos; /* pointer to current position in the buffer */
+ u32 version;
+};
+
+#endif /* __MODULEINTERFACE_H */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,681 @@
This patch implements three distinct chunks.
- list management, for profiles loaded into the system (profile_list) and for
the set of confined tasks (subdomain_list)
- the proc/pid/attr interface used by userspace for setprofile (forcing
a task into a new profile) and changehat (switching a task into one of it's
defined sub profiles). Access to change_hat is normally via code provided
in libapparmor. See the overview posting for more information in change hat.
- capability utility functions (for displaying capability names)
Signed-off-by: Tony Jones <tonyj@suse.de>
---
security/apparmor/capabilities.c | 54 ++++++
security/apparmor/list.c | 268 +++++++++++++++++++++++++++++++
security/apparmor/procattr.c | 327 +++++++++++++++++++++++++++++++++++++++
3 files changed, 649 insertions(+)
--- security/apparmor/capabilities.c.orig
+++ security/apparmor/capabilities.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * AppArmor capability definitions
+ */
+
+#include "apparmor.h"
+
+static const char *cap_names[] = {
+ "chown",
+ "dac_override",
+ "dac_read_search",
+ "fowner",
+ "fsetid",
+ "kill",
+ "setgid",
+ "setuid",
+ "setpcap",
+ "linux_immutable",
+ "net_bind_service",
+ "net_broadcast",
+ "net_admin",
+ "net_raw",
+ "ipc_lock",
+ "ipc_owner",
+ "sys_module",
+ "sys_rawio",
+ "sys_chroot",
+ "sys_ptrace",
+ "sys_pacct",
+ "sys_admin",
+ "sys_boot",
+ "sys_nice",
+ "sys_resource",
+ "sys_time",
+ "sys_tty_config",
+ "mknod",
+ "lease"
+};
+
+const char *capability_to_name(unsigned int cap)
+{
+ const char *name;
+
+ name = (cap < (sizeof(cap_names) / sizeof(char *))
+ ? cap_names[cap] : "invalid-capability");
+
+ return name;
+}
--- security/apparmor/list.c.orig
+++ security/apparmor/list.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 1998-2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * AppArmor Profile List Management
+ */
+
+#include <linux/seq_file.h>
+#include "apparmor.h"
+#include "inline.h"
+
+/* list of all profiles and lock */
+static LIST_HEAD(profile_list);
+static rwlock_t profile_lock = RW_LOCK_UNLOCKED;
+
+/* list of all subdomains and lock */
+static LIST_HEAD(subdomain_list);
+static rwlock_t subdomain_lock = RW_LOCK_UNLOCKED;
+
+/**
+ * aa_profilelist_find
+ * @name: profile name (program name)
+ *
+ * Search the profile list for profile @name. Return refcounted profile on
+ * success, NULL on failure.
+ */
+struct aaprofile *aa_profilelist_find(const char *name)
+{
+ struct aaprofile *p = NULL;
+ if (name) {
+ read_lock(&profile_lock);
+ p = __aa_find_profile(name, &profile_list);
+ read_unlock(&profile_lock);
+ }
+ return p;
+}
+
+/**
+ * aa_profilelist_add - add new profile to list
+ * @profile: new profile to add to list
+ *
+ * NOTE: Caller must allocate necessary reference count that will be used
+ * by the profile_list. This is because profile allocation alloc_aaprofile()
+ * returns an unreferenced object with a initial count of %1.
+ *
+ * Return %1 on success, %0 on failure (already exists)
+ */
+int aa_profilelist_add(struct aaprofile *profile)
+{
+ struct aaprofile *old_profile;
+ int ret = 0;
+
+ if (!profile)
+ goto out;
+
+ write_lock(&profile_lock);
+ old_profile = __aa_find_profile(profile->name, &profile_list);
+ if (old_profile) {
+ put_aaprofile(old_profile);
+ goto out;
+ }
+
+ list_add(&profile->list, &profile_list);
+ ret = 1;
+ out:
+ write_unlock(&profile_lock);
+ return ret;
+}
+
+/**
+ * aa_profilelist_remove - remove a profile from the list by name
+ * @name: name of profile to be removed
+ *
+ * If the profile exists remove profile from list and return its reference.
+ * The reference count on profile is not decremented and should be decremented
+ * when the profile is no longer needed
+ */
+struct aaprofile *aa_profilelist_remove(const char *name)
+{
+ struct aaprofile *profile = NULL;
+ struct aaprofile *p, *tmp;
+
+ if (!name)
+ goto out;
+
+ write_lock(&profile_lock);
+ list_for_each_entry_safe(p, tmp, &profile_list, list) {
+ if (!strcmp(p->name, name)) {
+ list_del_init(&p->list);
+ /* mark old profile as stale */
+ p->isstale = 1;
+ profile = p;
+ break;
+ }
+ }
+ write_unlock(&profile_lock);
+
+out:
+ return profile;
+}
+
+/**
+ * aa_profilelist_replace - replace a profile on the list
+ * @profile: new profile
+ *
+ * Replace a profile on the profile list. Find the old profile by name in
+ * the list, and replace it with the new profile. NOTE: Caller must allocate
+ * necessary initial reference count for new profile as aa_profilelist_add().
+ *
+ * This is an atomic list operation. Returns the old profile (which is still
+ * refcounted) if there was one, or NULL.
+ */
+struct aaprofile *aa_profilelist_replace(struct aaprofile *profile)
+{
+ struct aaprofile *oldprofile;
+
+ write_lock(&profile_lock);
+ oldprofile = __aa_find_profile(profile->name, &profile_list);
+ if (oldprofile) {
+ list_del_init(&oldprofile->list);
+ /* mark old profile as stale */
+ oldprofile->isstale = 1;
+
+ /* __aa_find_profile incremented count, so adjust down */
+ put_aaprofile(oldprofile);
+ }
+
+ list_add(&profile->list, &profile_list);
+ write_unlock(&profile_lock);
+
+ return oldprofile;
+}
+
+/**
+ * aa_profilelist_release - Remove all profiles from profile_list
+ */
+void aa_profilelist_release(void)
+{
+ struct aaprofile *p, *tmp;
+
+ write_lock(&profile_lock);
+ list_for_each_entry_safe(p, tmp, &profile_list, list) {
+ list_del_init(&p->list);
+ put_aaprofile(p);
+ }
+ write_unlock(&profile_lock);
+}
+
+/**
+ * aa_subdomainlist_add - Add subdomain to subdomain_list
+ * @sd: new subdomain
+ */
+void aa_subdomainlist_add(struct subdomain *sd)
+{
+ unsigned long flags;
+
+ if (!sd) {
+ AA_INFO("%s: bad subdomain\n", __FUNCTION__);
+ return;
+ }
+
+ write_lock_irqsave(&subdomain_lock, flags);
+ /* new subdomains must be added to the end of the list due to a
+ * subtle interaction between fork and profile replacement.
+ */
+ list_add_tail(&sd->list, &subdomain_list);
+ write_unlock_irqrestore(&subdomain_lock, flags);
+}
+
+/**
+ * aa_subdomainlist_remove - Remove subdomain from subdomain_list
+ * @sd: subdomain to be removed
+ */
+void aa_subdomainlist_remove(struct subdomain *sd)
+{
+ unsigned long flags;
+
+ if (sd) {
+ write_lock_irqsave(&subdomain_lock, flags);
+ list_del_init(&sd->list);
+ write_unlock_irqrestore(&subdomain_lock, flags);
+ }
+}
+
+/**
+ * aa_subdomainlist_iterate - iterate over the subdomain list applying @func
+ * @func: method to be called for each element
+ * @cookie: user passed data
+ *
+ * Iterate over subdomain list applying @func, stop when @func returns
+ * non zero
+ */
+void aa_subdomainlist_iterate(aa_iter func, void *cookie)
+{
+ struct subdomain *node;
+ int ret = 0;
+ unsigned long flags;
+
+ read_lock_irqsave(&subdomain_lock, flags);
+ list_for_each_entry(node, &subdomain_list, list) {
+ ret = (*func) (node, cookie);
+ if (ret != 0)
+ break;
+ }
+ read_unlock_irqrestore(&subdomain_lock, flags);
+}
+
+/**
+ * aa_subdomainlist_release - Remove all subdomains from subdomain_list
+ */
+void aa_subdomainlist_release()
+{
+ struct subdomain *node, *tmp;
+ unsigned long flags;
+
+ write_lock_irqsave(&subdomain_lock, flags);
+ list_for_each_entry_safe(node, tmp, &subdomain_list, list) {
+ list_del_init(&node->list);
+ }
+ write_unlock_irqrestore(&subdomain_lock, flags);
+}
+
+/* seq_file helper routines
+ * Used by apparmorfs.c to iterate over profile_list
+ */
+static void *p_start(struct seq_file *f, loff_t *pos)
+{
+ struct aaprofile *node;
+ loff_t l = *pos;
+
+ read_lock(&profile_lock);
+ list_for_each_entry(node, &profile_list, list)
+ if (!l--)
+ return node;
+ return NULL;
+}
+
+static void *p_next(struct seq_file *f, void *p, loff_t *pos)
+{
+ struct list_head *lh = ((struct aaprofile *)p)->list.next;
+ (*pos)++;
+ return lh == &profile_list ?
+ NULL : list_entry(lh, struct aaprofile, list);
+}
+
+static void p_stop(struct seq_file *f, void *v)
+{
+ read_unlock(&profile_lock);
+}
+
+static int seq_show_profile(struct seq_file *f, void *v)
+{
+ struct aaprofile *profile = (struct aaprofile *)v;
+ seq_printf(f, "%s (%s)\n", profile->name,
+ PROFILE_COMPLAIN(profile) ? "complain" : "enforce");
+ return 0;
+}
+
+struct seq_operations apparmorfs_profiles_op = {
+ .start = p_start,
+ .next = p_next,
+ .stop = p_stop,
+ .show = seq_show_profile,
+};
--- security/apparmor/procattr.c.orig
+++ security/apparmor/procattr.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * AppArmor /proc/pid/attr handling
+ */
+
+/* for isspace */
+#include <linux/ctype.h>
+
+#include "apparmor.h"
+#include "inline.h"
+
+size_t aa_getprocattr(struct aaprofile *active, char *str, size_t size)
+{
+ int error = -EACCES; /* default to a perm denied */
+ size_t len;
+
+ if (active) {
+ size_t lena, lenm, lenp = 0;
+ const char *enforce_str = " (enforce)";
+ const char *complain_str = " (complain)";
+ const char *mode_str =
+ PROFILE_COMPLAIN(active) ? complain_str : enforce_str;
+
+ lenm = strlen(mode_str);
+
+ lena = strlen(active->name);
+
+ len = lena;
+ if (IN_SUBPROFILE(active)) {
+ lenp = strlen(BASE_PROFILE(active)->name);
+ len += (lenp + 1); /* +1 for ^ */
+ }
+ /* DONT null terminate strings we output via proc */
+ len += (lenm + 1); /* for \n */
+
+ if (len <= size) {
+ if (lenp) {
+ memcpy(str, BASE_PROFILE(active)->name,
+ lenp);
+ str += lenp;
+ *str++ = '^';
+ }
+
+ memcpy(str, active->name, lena);
+ str += lena;
+ memcpy(str, mode_str, lenm);
+ str += lenm;
+ *str++ = '\n';
+ error = len;
+ } else {
+ error = -ERANGE;
+ }
+ } else {
+ const char *unconstrained_str = "unconstrained\n";
+ len = strlen(unconstrained_str);
+
+ /* DONT null terminate strings we output via proc */
+ if (len <= size) {
+ memcpy(str, unconstrained_str, len);
+ error = len;
+ } else {
+ error = -ERANGE;
+ }
+ }
+
+ return error;
+
+}
+
+int aa_setprocattr_changehat(char *hatinfo, size_t infosize)
+{
+ int error = -EINVAL;
+ char *token = NULL, *hat, *smagic, *tmp;
+ u32 magic;
+ int rc, len, consumed;
+ unsigned long flags;
+
+ AA_DEBUG("%s: %p %zd\n", __FUNCTION__, hatinfo, infosize);
+
+ /* strip leading white space */
+ while (infosize && isspace(*hatinfo)) {
+ hatinfo++;
+ infosize--;
+ }
+
+ if (infosize == 0)
+ goto out;
+
+ /*
+ * Copy string to a new buffer so we can play with it
+ * It may be zero terminated but we add a trailing 0
+ * for 100% safety
+ */
+ token = kmalloc(infosize + 1, GFP_KERNEL);
+
+ if (!token) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(token, hatinfo, infosize);
+ token[infosize] = 0;
+
+ /* error is INVAL until we have at least parsed something */
+ error = -EINVAL;
+
+ tmp = token;
+ while (*tmp && *tmp != '^') {
+ tmp++;
+ }
+
+ if (!*tmp || tmp == token) {
+ AA_WARN("%s: Invalid input '%s'\n", __FUNCTION__, token);
+ goto out;
+ }
+
+ /* split magic and hat into two strings */
+ *tmp = 0;
+ smagic = token;
+
+ /*
+ * Initially set consumed=strlen(magic), as if sscanf
+ * consumes all input via the %x it will not process the %n
+ * directive. Otherwise, if sscanf does not consume all the
+ * input it will process the %n and update consumed.
+ */
+ consumed = len = strlen(smagic);
+
+ rc = sscanf(smagic, "%x%n", &magic, &consumed);
+
+ if (rc != 1 || consumed != len) {
+ AA_WARN("%s: Invalid hex magic %s\n",
+ __FUNCTION__,
+ smagic);
+ goto out;
+ }
+
+ hat = tmp + 1;
+
+ if (!*hat)
+ hat = NULL;
+
+ if (!hat && !magic) {
+ AA_WARN("%s: Invalid input, NULL hat and NULL magic\n",
+ __FUNCTION__);
+ goto out;
+ }
+
+ AA_DEBUG("%s: Magic 0x%x Hat '%s'\n",
+ __FUNCTION__, magic, hat ? hat : NULL);
+
+ spin_lock_irqsave(&sd_lock, flags);
+ error = aa_change_hat(hat, magic);
+ spin_unlock_irqrestore(&sd_lock, flags);
+
+out:
+ if (token) {
+ memset(token, 0, infosize);
+ kfree(token);
+ }
+
+ return error;
+}
+
+int aa_setprocattr_setprofile(struct task_struct *p, char *profilename,
+ size_t profilesize)
+{
+ int error = -EINVAL;
+ struct aaprofile *profile = NULL;
+ struct subdomain *sd;
+ char *name = NULL;
+ unsigned long flags;
+
+ AA_DEBUG("%s: current %s(%d)\n",
+ __FUNCTION__, current->comm, current->pid);
+
+ /* strip leading white space */
+ while (profilesize && isspace(*profilename)) {
+ profilename++;
+ profilesize--;
+ }
+
+ if (profilesize == 0)
+ goto out;
+
+ /*
+ * Copy string to a new buffer so we guarantee it is zero
+ * terminated
+ */
+ name = kmalloc(profilesize + 1, GFP_KERNEL);
+
+ if (!name) {
+ error = -ENOMEM;
+ goto out;
+ }
+
+ strncpy(name, profilename, profilesize);
+ name[profilesize] = 0;
+
+ repeat:
+ if (strcmp(name, "unconstrained") != 0) {
+ profile = aa_profilelist_find(name);
+ if (!profile) {
+ AA_WARN("%s: Unable to switch task %s(%d) to profile"
+ "'%s'. No such profile.\n",
+ __FUNCTION__,
+ p->comm, p->pid,
+ name);
+
+ error = -EINVAL;
+ goto out;
+ }
+ }
+
+ spin_lock_irqsave(&sd_lock, flags);
+
+ sd = AA_SUBDOMAIN(p->security);
+
+ /* switch to unconstrained */
+ if (!profile) {
+ if (__aa_is_confined(sd)) {
+ AA_WARN("%s: Unconstraining task %s(%d) "
+ "profile %s active %s\n",
+ __FUNCTION__,
+ p->comm, p->pid,
+ BASE_PROFILE(sd->active)->name,
+ sd->active->name);
+
+ aa_switch_unconfined(sd);
+ } else {
+ AA_WARN("%s: task %s(%d) "
+ "is already unconstrained\n",
+ __FUNCTION__, p->comm, p->pid);
+ }
+ } else {
+ if (!sd) {
+ /* this task was created before module was
+ * loaded, allocate a subdomain
+ */
+ AA_WARN("%s: task %s(%d) has no subdomain\n",
+ __FUNCTION__, p->comm, p->pid);
+
+ /* unlock so we can safely GFP_KERNEL */
+ spin_unlock_irqrestore(&sd_lock, flags);
+
+ sd = alloc_subdomain(p);
+ if (!sd) {
+ AA_WARN("%s: Unable to allocate subdomain for "
+ "task %s(%d). Cannot confine task to "
+ "profile %s\n",
+ __FUNCTION__,
+ p->comm, p->pid,
+ name);
+
+ error = -ENOMEM;
+ put_aaprofile(profile);
+
+ goto out;
+ }
+
+ spin_lock_irqsave(&sd_lock, flags);
+ if (!AA_SUBDOMAIN(p->security)) {
+ p->security = sd;
+ } else { /* race */
+ free_subdomain(sd);
+ sd = AA_SUBDOMAIN(p->security);
+ }
+ }
+
+ /* ensure the profile hasn't been replaced */
+
+ if (unlikely(profile->isstale)) {
+ WARN_ON(profile == null_complain_profile);
+
+ /* drop refcnt obtained from earlier get_aaprofile */
+ put_aaprofile(profile);
+ profile = aa_profilelist_find(name);
+
+ if (!profile) {
+ /* Race, profile was removed. */
+ spin_unlock_irqrestore(&sd_lock, flags);
+ goto repeat;
+ }
+ }
+
+ /* we do not do a normal task replace since we are not
+ * replacing with the same profile.
+ * If existing process is in a hat, it will be moved
+ * into the new parent profile, even if this new
+ * profile has a identical named hat.
+ */
+
+ AA_WARN("%s: Switching task %s(%d) "
+ "profile %s active %s to new profile %s\n",
+ __FUNCTION__,
+ p->comm, p->pid,
+ sd->active ? BASE_PROFILE(sd->active)->name :
+ "unconstrained",
+ sd->active ? sd->active->name : "unconstrained",
+ name);
+
+ aa_switch(sd, profile);
+
+ put_aaprofile(profile); /* drop ref we obtained above
+ * from aa_profilelist_find
+ */
+
+ /* Reset magic in case we were in a subhat before
+ * This is the only case where we zero the magic after
+ * calling aa_switch
+ */
+ sd->hat_magic = 0;
+ }
+
+ spin_unlock_irqrestore(&sd_lock, flags);
+
+out:
+ kfree(name);
+
+ return error;
+}
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,246 @@
The file match.h specifies a sub module interface consisting of the following
functions:
aamatch_alloc
aamatch_free
Allocates/deallocates submodule specific data used by each
loaded profile (policy).
aamatch_features
Returns the list of features implemented by the submodule.
These are literal, tailglob ("/path/**" match all paths
below /path) and pattern (full shell based pathname expansion).
aamatch_serialize
Called by the module interface to serialize submodule specific
data from userspace.
aamatch_match
Called to perform matching on a generated pathname.
The submodule submitted here implements only "literal" and "tailglob".
The version included with SuSE Linux implements "pattern" but via a method
that is not acceptable for mainline inclusion. We plan on developing
a new submodule as soon as possible that will implement the missing
functionality of the SuSE release using the textsearch framework and
a new bounded textsearch algorithm acceptable for subsequent inclusion
into the mainline kernel.
Signed-off-by: Tony Jones <tonyj@suse.de>
---
security/apparmor/match/Makefile | 5 +
security/apparmor/match/match.h | 132 ++++++++++++++++++++++++++++++++
security/apparmor/match/match_default.c | 57 +++++++++++++
3 files changed, 194 insertions(+)
--- security/apparmor/match/Makefile.orig
+++ security/apparmor/match/Makefile
@@ -0,0 +1,5 @@
+# Makefile for AppArmor aamatch submodule
+#
+obj-$(CONFIG_SECURITY_APPARMOR) += aamatch_default.o
+
+aamatch_default-y := match_default.o
--- security/apparmor/match/match.h.orig
+++ security/apparmor/match/match.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2002-2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * AppArmor submodule (match) prototypes
+ */
+
+#ifndef __MATCH_H
+#define __MATCH_H
+
+#include "../module_interface.h"
+#include "../apparmor.h"
+
+/* The following functions implement an interface used by the primary
+ * AppArmor module to perform name matching (n.b. "AppArmor" was previously
+ * called "SubDomain").
+
+ * aamatch_alloc
+ * aamatch_free
+ * aamatch_features
+ * aamatch_serialize
+ * aamatch_match
+ *
+ * The intent is for the primary module to export (via virtual fs entries)
+ * the features provided by the submodule (aamatch_features) so that the
+ * parser may only load policy that can be supported.
+ *
+ * The primary module will call aamatch_serialize to allow the submodule
+ * to consume submodule specific data from parser data stream and will call
+ * aamatch_match to determine if a pathname matches an aa_entry.
+ */
+
+typedef int (*aamatch_serializecb)
+ (struct aa_ext *, enum aa_code, void *, const char *);
+
+/**
+ * aamatch_alloc: allocate extradata (if necessary)
+ * @type: type of entry being allocated
+ * Return value: NULL indicates no data was allocated (ERR_PTR(x) on error)
+ */
+extern void* aamatch_alloc(enum entry_match_type type);
+
+/**
+ * aamatch_free: release data allocated by aamatch_alloc
+ * @entry_extradata: data previously allocated by aamatch_alloc
+ */
+extern void aamatch_free(void *entry_extradata);
+
+/**
+ * aamatch_features: return match types supported
+ * Return value: space seperated string (of types supported - use type=value
+ * to indicate variants of a type)
+ */
+extern const char* aamatch_features(void);
+
+/**
+ * aamatch_serialize: serialize extradata
+ * @entry_extradata: data previously allocated by aamatch_alloc
+ * @e: input stream
+ * @cb: callback fn (consume incoming data stream)
+ * Return value: 0 success, -ve error
+ */
+extern int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
+ aamatch_serializecb cb);
+
+/**
+ * aamatch_match: determine if pathname matches entry
+ * @pathname: pathname to verify
+ * @entry_name: entry name
+ * @type: type of entry
+ * @entry_extradata: data previously allocated by aamatch_alloc
+ * Return value: 1 match, 0 othersise
+ */
+extern unsigned int aamatch_match(const char *pathname, const char *entry_name,
+ enum entry_match_type type,
+ void *entry_extradata);
+
+
+/**
+ * sd_getmatch_type - return string representation of entry_match_type
+ * @type: entry match type
+ */
+static inline const char *sd_getmatch_type(enum entry_match_type type)
+{
+ const char *names[] = {
+ "aa_entry_literal",
+ "aa_entry_tailglob",
+ "aa_entry_pattern",
+ "aa_entry_invalid"
+ };
+
+ if (type >= aa_entry_invalid) {
+ type = aa_entry_invalid;
+ }
+
+ return names[type];
+}
+
+/**
+ * aamatch_match_common - helper function to check if a pathname matches
+ * a literal/tailglob
+ * @path: path requested to search for
+ * @entry_name: name from aa_entry
+ * @type: type of entry
+ */
+static inline int aamatch_match_common(const char *path,
+ const char *entry_name,
+ enum entry_match_type type)
+{
+ int retval;
+
+ /* literal, no pattern matching characters */
+ if (type == aa_entry_literal) {
+ retval = (strcmp(entry_name, path) == 0);
+ /* trailing ** glob pattern */
+ } else if (type == aa_entry_tailglob) {
+ retval = (strncmp(entry_name, path,
+ strlen(entry_name) - 2) == 0);
+ } else {
+ AA_WARN("%s: Invalid entry_match_type %d\n",
+ __FUNCTION__, type);
+ retval = 0;
+ }
+
+ return retval;
+}
+
+#endif /* __MATCH_H */
--- security/apparmor/match/match_default.c.orig
+++ security/apparmor/match/match_default.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2002-2005 Novell/SUSE
+ *
+ * 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, version 2 of the
+ * License.
+ *
+ * http://forge.novell.com/modules/xfmod/project/?apparmor
+ *
+ * AppArmor default match submodule (literal and tailglob)
+ */
+
+#include <linux/module.h>
+#include "match.h"
+
+static const char *features="literal tailglob";
+
+void* aamatch_alloc(enum entry_match_type type)
+{
+ return NULL;
+}
+
+void aamatch_free(void *ptr)
+{
+}
+
+const char *aamatch_features(void)
+{
+ return features;
+}
+
+int aamatch_serialize(void *entry_extradata, struct aa_ext *e,
+ aamatch_serializecb cb)
+{
+ return 0;
+}
+
+unsigned int aamatch_match(const char *pathname, const char *entry_name,
+ enum entry_match_type type, void *entry_extradata)
+{
+ int ret;
+
+ ret = aamatch_match_common(pathname, entry_name, type);
+
+ return ret;
+}
+
+EXPORT_SYMBOL_GPL(aamatch_alloc);
+EXPORT_SYMBOL_GPL(aamatch_free);
+EXPORT_SYMBOL_GPL(aamatch_features);
+EXPORT_SYMBOL_GPL(aamatch_serialize);
+EXPORT_SYMBOL_GPL(aamatch_match);
+
+MODULE_DESCRIPTION("AppArmor match module (aamatch) [default]");
+MODULE_AUTHOR("Tony Jones <tonyj@suse.de>");
+MODULE_LICENSE("GPL");
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,58 @@
This patch adds AppArmor support to the audit subsystem.
It creates id 1500 (already included in the the upstream auditd package) for
AppArmor messages.
It also exports the audit_log_vformat function (analagous to having both
printk and vprintk exported).
Signed-off-by: Tony Jones <tonyj@suse.de>
---
include/linux/audit.h | 5 +++++
kernel/audit.c | 3 ++-
2 files changed, 7 insertions(+), 1 deletion(-)
--- linux-2.6.17-rc1.orig/include/linux/audit.h
+++ linux-2.6.17-rc1/include/linux/audit.h
@@ -95,6 +95,8 @@
#define AUDIT_LAST_KERN_ANOM_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
+#define AUDIT_AA 1500 /* AppArmor audit */
+
#define AUDIT_KERNEL 2000 /* Asynchronous audit record. NOT A REQUEST. */
/* Rule flags */
@@ -349,6 +351,9 @@
__attribute__((format(printf,4,5)));
extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
+extern void audit_log_vformat(struct audit_buffer *ab,
+ const char *fmt, va_list args)
+ __attribute__((format(printf,2,0)));
extern void audit_log_format(struct audit_buffer *ab,
const char *fmt, ...)
__attribute__((format(printf,2,3)));
--- linux-2.6.17-rc1.orig/kernel/audit.c
+++ linux-2.6.17-rc1/kernel/audit.c
@@ -797,7 +797,7 @@
* will be called a second time. Currently, we assume that a printk
* can't format message larger than 1024 bytes, so we don't either.
*/
-static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
+void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
va_list args)
{
int len, avail;
@@ -999,4 +999,5 @@
EXPORT_SYMBOL(audit_log_start);
EXPORT_SYMBOL(audit_log_end);
EXPORT_SYMBOL(audit_log_format);
+EXPORT_SYMBOL(audit_log_vformat);
EXPORT_SYMBOL(audit_log);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,170 @@
This patch adds a new function d_path_flags which takes an additional flags
parameter. Adding a new function rather than ammending the existing d_path
was done to avoid impact on the current users.
It is not essential for inclusion with AppArmor (the apparmor_mediation.patch
can easily be revised to use plain d_path) but it enables cleaner code
["(delete)" handling] and closes a loophole with pathname generation for
chrooted tasks.
It currently adds two flags:
DPATH_SYSROOT:
d_path should generate a path from the system root rather than the
task's current root.
For AppArmor this enables generation of absolute pathnames in all
cases. Currently when a task is chrooted, file access is reported
relative to the chroot. Because it is currently not possible to
obtain the absolute path in an SMP safe way, without this patch
AppArmor will have to report chroot-relative pathnames.
DPATH_NODELETED:
d_path should not append "(deleted)" to unhashed entries. Sometimes
this information is not useful for the caller and the string can
exist as the suffix of a valid pathname.
Signed-off-by: Tony Jones <tonyj@suse.de>
---
fs/dcache.c | 48 ++++++++++++++++++++++++++++++++----------------
include/linux/dcache.h | 7 +++++++
2 files changed, 39 insertions(+), 16 deletions(-)
--- linux-2.6.17-rc1.orig/fs/dcache.c
+++ linux-2.6.17-rc1/fs/dcache.c
@@ -1381,9 +1381,11 @@
* @rootmnt: vfsmnt to which the root dentry belongs
* @buffer: buffer to return value in
* @buflen: buffer length
+ * @flags: control flags
*
* Convert a dentry into an ASCII path name. If the entry has been deleted
- * the string " (deleted)" is appended. Note that this is ambiguous.
+ * and DPATH_NODELETED is not specified in flags then the string " (deleted)"
+ * is appended. Note that this is ambiguous.
*
* Returns the buffer or an error code if the path was too long.
*
@@ -1391,7 +1393,7 @@
*/
static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
struct dentry *root, struct vfsmount *rootmnt,
- char *buffer, int buflen)
+ char *buffer, int buflen, unsigned int flags)
{
char * end = buffer+buflen;
char * retval;
@@ -1399,7 +1401,8 @@
*--end = '\0';
buflen--;
- if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
+ if (!(flags & DPATH_NODELETED) &&
+ !IS_ROOT(dentry) && d_unhashed(dentry)) {
buflen -= 10;
end -= 10;
if (buflen < 0)
@@ -1416,7 +1419,8 @@
for (;;) {
struct dentry * parent;
- if (dentry == root && vfsmnt == rootmnt)
+ if (!(flags & DPATH_SYSROOT) &&
+ dentry == root && vfsmnt == rootmnt)
break;
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
/* Global root? */
@@ -1458,25 +1462,36 @@
}
/* write full pathname into buffer and return start of pathname */
-char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
- char *buf, int buflen)
+char * d_path_flags(struct dentry *dentry, struct vfsmount *vfsmnt,
+ char *buf, int buflen, unsigned int flags)
{
char *res;
- struct vfsmount *rootmnt;
- struct dentry *root;
+ struct vfsmount *rootmnt = NULL;
+ struct dentry *root = NULL;
- read_lock(&current->fs->lock);
- rootmnt = mntget(current->fs->rootmnt);
- root = dget(current->fs->root);
- read_unlock(&current->fs->lock);
+ if (!(flags & DPATH_SYSROOT)){
+ read_lock(&current->fs->lock);
+ rootmnt = mntget(current->fs->rootmnt);
+ root = dget(current->fs->root);
+ read_unlock(&current->fs->lock);
+ }
spin_lock(&dcache_lock);
- res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen);
+ res = __d_path(dentry, vfsmnt, root, rootmnt, buf, buflen, flags);
spin_unlock(&dcache_lock);
- dput(root);
- mntput(rootmnt);
+ if (!(flags & DPATH_SYSROOT)){
+ dput(root);
+ mntput(rootmnt);
+ }
return res;
}
+/* original d_path without support for flags */
+char * d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
+ char *buf, int buflen)
+{
+ return d_path_flags(dentry, vfsmnt, buf, buflen, 0);
+}
+
/*
* NOTE! The user-level library version returns a
* character pointer. The kernel system call just
@@ -1519,7 +1534,7 @@
unsigned long len;
char * cwd;
- cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
+ cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE, 0);
spin_unlock(&dcache_lock);
error = PTR_ERR(cwd);
@@ -1771,6 +1786,7 @@
EXPORT_SYMBOL(d_invalidate);
EXPORT_SYMBOL(d_lookup);
EXPORT_SYMBOL(d_move);
+EXPORT_SYMBOL(d_path_flags);
EXPORT_SYMBOL(d_path);
EXPORT_SYMBOL(d_prune_aliases);
EXPORT_SYMBOL(d_rehash);
--- linux-2.6.17-rc1.orig/include/linux/dcache.h
+++ linux-2.6.17-rc1/include/linux/dcache.h
@@ -164,6 +164,10 @@
#define DCACHE_INOTIFY_PARENT_WATCHED 0x0020 /* Parent inode is watched */
+/* dpath flags */
+#define DPATH_SYSROOT 0x0001 /* continue past fsroot (chroot) */
+#define DPATH_NODELETED 0x0002 /* do not append " (deleted)" */
+
extern spinlock_t dcache_lock;
/**
@@ -281,6 +285,9 @@
extern int d_validate(struct dentry *, struct dentry *);
extern char * d_path(struct dentry *, struct vfsmount *, char *, int);
+
+extern char * d_path_flags(struct dentry *, struct vfsmount *, char *, int,
+ unsigned int);
/* Allocation counts.. */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,53 @@
This patch exports the namespace_sem semaphore.
The shared subtree patches which went into 2.6.15-rc1 replaced the old
namespace semaphore which used to be per namespace (and visible) with a
new single static semaphore.
The reason for this change is that currently visibility of vfsmount information
to the LSM hooks is fairly patchy. Either there is no passed parameter or
it can be NULL. For the case of the former, several LSM hooks that we
require to mediate have no vfsmount/nameidata passed. We previously (mis)used
the visibility of the old per namespace semaphore to walk the processes
namespace looking for vfsmounts with a root dentry matching the dentry we were
trying to mediate.
Clearly this is not viable long term strategy and changes working towards
passing a vfsmount to all relevant LSM hooks would seem necessary (and also
useful for other users of LSM). Alternative suggestions and ideas are welcomed.
Signed-off-by: Tony Jones <tonyj@suse.de>
---
fs/namespace.c | 3 ++-
include/linux/namespace.h | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)
--- linux-2.6.17-rc1.orig/fs/namespace.c
+++ linux-2.6.17-rc1/fs/namespace.c
@@ -46,7 +46,8 @@
static struct list_head *mount_hashtable __read_mostly;
static int hash_mask __read_mostly, hash_bits __read_mostly;
static kmem_cache_t *mnt_cache __read_mostly;
-static struct rw_semaphore namespace_sem;
+struct rw_semaphore namespace_sem;
+EXPORT_SYMBOL_GPL(namespace_sem);
/* /sys/fs */
decl_subsys(fs, NULL, NULL);
--- linux-2.6.17-rc1.orig/include/linux/namespace.h
+++ linux-2.6.17-rc1/include/linux/namespace.h
@@ -5,6 +5,8 @@
#include <linux/mount.h>
#include <linux/sched.h>
+extern struct rw_semaphore namespace_sem;
+
struct namespace {
atomic_t count;
struct vfsmount * root;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

View File

@ -0,0 +1,59 @@
Subject: Export audit subsystem for use by modules
Patch-mainline: no
Adds necessary export symbols for audit subsystem routines.
Changes audit_log_vformat to be externally visible (analagous to vprintf)
Patch is not in mainline -- pending AppArmor code submission to lkml
Index: linux-2.6.17/include/linux/audit.h
===================================================================
--- linux-2.6.17.orig/include/linux/audit.h
+++ linux-2.6.17/include/linux/audit.h
@@ -92,6 +92,8 @@
#define AUDIT_MAC_STATUS 1404 /* Changed enforcing,permissive,off */
#define AUDIT_MAC_CONFIG_CHANGE 1405 /* Changes to booleans */
+#define AUDIT_SD 1500 /* AppArmor (SubDomain) audit */
+
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
#define AUDIT_ANOM_PROMISCUOUS 1700 /* Device changed promiscuous mode */
@@ -357,6 +359,9 @@
__attribute__((format(printf,4,5)));
extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask, int type);
+extern void audit_log_vformat(struct audit_buffer *ab,
+ const char *fmt, va_list args)
+ __attribute__((format(printf,2,0)));
extern void audit_log_format(struct audit_buffer *ab,
const char *fmt, ...)
__attribute__((format(printf,2,3)));
Index: linux-2.6.17/kernel/audit.c
===================================================================
--- linux-2.6.17.orig/kernel/audit.c
+++ linux-2.6.17/kernel/audit.c
@@ -893,7 +893,7 @@
* will be called a second time. Currently, we assume that a printk
* can't format message larger than 1024 bytes, so we don't either.
*/
-static void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
+void audit_log_vformat(struct audit_buffer *ab, const char *fmt,
va_list args)
{
int len, avail;
@@ -1092,7 +1092,10 @@
}
}
-EXPORT_SYMBOL(audit_log_start);
-EXPORT_SYMBOL(audit_log_end);
-EXPORT_SYMBOL(audit_log_format);
-EXPORT_SYMBOL(audit_log);
+EXPORT_SYMBOL_GPL(audit_log_start);
+EXPORT_SYMBOL_GPL(audit_log_vformat);
+EXPORT_SYMBOL_GPL(audit_log_format);
+EXPORT_SYMBOL_GPL(audit_log_untrustedstring);
+EXPORT_SYMBOL_GPL(audit_log_d_path);
+EXPORT_SYMBOL_GPL(audit_log_end);
+EXPORT_SYMBOL_GPL(audit_log);

View File

@ -0,0 +1,36 @@
Subject: Export namespace semaphore
Patch-mainline: no
Export global namespace_sem (this used to be a per namespace semaphore).
Alas, this isn't going to win _any_ points for style.
Patch is not in mainline -- pending AppArmor code submission to lkml
Index: linux-2.6.17/fs/namespace.c
===================================================================
--- linux-2.6.17.orig/fs/namespace.c
+++ linux-2.6.17/fs/namespace.c
@@ -46,7 +46,8 @@
static struct list_head *mount_hashtable __read_mostly;
static int hash_mask __read_mostly, hash_bits __read_mostly;
static kmem_cache_t *mnt_cache __read_mostly;
-static struct rw_semaphore namespace_sem;
+struct rw_semaphore namespace_sem;
+EXPORT_SYMBOL_GPL(namespace_sem);
/* /sys/fs */
decl_subsys(fs, NULL, NULL);
Index: linux-2.6.17/include/linux/namespace.h
===================================================================
--- linux-2.6.17.orig/include/linux/namespace.h
+++ linux-2.6.17/include/linux/namespace.h
@@ -5,6 +5,9 @@
#include <linux/mount.h>
#include <linux/sched.h>
+/* exported for AppArmor (SubDomain) */
+extern struct rw_semaphore namespace_sem;
+
struct namespace {
atomic_t count;
struct vfsmount * root;

View File

@ -0,0 +1,9 @@
MD5 cd5d67dc1d3514ec240497efff0f8726 genpatches-2.6.17-1.base.tar.bz2 3337
RMD160 f9b5621fed8fcfee7da697d89097842287b41b24 genpatches-2.6.17-1.base.tar.bz2 3337
SHA256 2208b72729dce6daef7dc5700192aec0ae17327c794681621d2123f0c483ae21 genpatches-2.6.17-1.base.tar.bz2 3337
MD5 0b6385904bccbd9d6c5508565e5c76ff genpatches-2.6.17-1.extras.tar.bz2 138704
RMD160 14b17e02b7893e6b023bee9e1b40f4bc85a30f05 genpatches-2.6.17-1.extras.tar.bz2 138704
SHA256 fa10ec7d3d74c8bf57fb3bd01c33f83dcca3c1e4cd4601937cc2ef904cce1dfe genpatches-2.6.17-1.extras.tar.bz2 138704
MD5 37ddefe96625502161f075b9d907f21e linux-2.6.17.tar.bz2 41272919
RMD160 26aad30c9a6610665c6c7d62401d79bf56a6a699 linux-2.6.17.tar.bz2 41272919
SHA256 ab0f647d52f124958439517df9e1ae0efda90cdb851f59f522fa1749f1d87d58 linux-2.6.17.tar.bz2 41272919

View File

@ -0,0 +1,9 @@
MD5 cd5d67dc1d3514ec240497efff0f8726 genpatches-2.6.17-1.base.tar.bz2 3337
RMD160 f9b5621fed8fcfee7da697d89097842287b41b24 genpatches-2.6.17-1.base.tar.bz2 3337
SHA256 2208b72729dce6daef7dc5700192aec0ae17327c794681621d2123f0c483ae21 genpatches-2.6.17-1.base.tar.bz2 3337
MD5 0b6385904bccbd9d6c5508565e5c76ff genpatches-2.6.17-1.extras.tar.bz2 138704
RMD160 14b17e02b7893e6b023bee9e1b40f4bc85a30f05 genpatches-2.6.17-1.extras.tar.bz2 138704
SHA256 fa10ec7d3d74c8bf57fb3bd01c33f83dcca3c1e4cd4601937cc2ef904cce1dfe genpatches-2.6.17-1.extras.tar.bz2 138704
MD5 37ddefe96625502161f075b9d907f21e linux-2.6.17.tar.bz2 41272919
RMD160 26aad30c9a6610665c6c7d62401d79bf56a6a699 linux-2.6.17.tar.bz2 41272919
SHA256 ab0f647d52f124958439517df9e1ae0efda90cdb851f59f522fa1749f1d87d58 linux-2.6.17.tar.bz2 41272919

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<herd>maintainer-wanted</herd>
</pkgmetadata>

View File

@ -0,0 +1,10 @@
# ChangeLog for sys-libs/libapparmor
# Copyright 1999-2006 Gentoo Foundation; Distributed under the GPL v2
# $Header: $
13 Aug 2006; Mario Fetka <mario-fetka@gmx.at>
+libapparmor-2.0_p6288.ebuild:
Initial Import of
Matthew Snelham <zeypher@sigalrm.com>
Apparmor ebuilds

View File

@ -0,0 +1,8 @@
DIST libapparmor-2.0-6288.tar.gz 20725 RMD160 5f4b8a443a23d4cd4a16b35ae8ebf65647683b2e SHA1 cd75d8631bdddb9e873cee5c6b3b45d12d94d416 SHA256 0aebaae48f1917a65c43683ad8f332301fcf46d4dcb392177a4750b245f42882
EBUILD libapparmor-2.0_p6288.ebuild 833 RMD160 2cb68e615d17cb3a8d2dec04eb3e7591ff0b7b0c SHA1 a532c94dad06f14345b10056425eb7a83f86fede SHA256 62b95ca2859d69d52a6c61953323a436445de006e99f696bac2372652c805a62
MD5 3211838fc17b65a3c9802623a6c7bf26 libapparmor-2.0_p6288.ebuild 833
RMD160 2cb68e615d17cb3a8d2dec04eb3e7591ff0b7b0c libapparmor-2.0_p6288.ebuild 833
SHA256 62b95ca2859d69d52a6c61953323a436445de006e99f696bac2372652c805a62 libapparmor-2.0_p6288.ebuild 833
MD5 b2a797f50971ce7df339c695782874b2 files/digest-libapparmor-2.0_p6288 259
RMD160 7088ab92b7dc5c741357ca3184eb79575a0832de files/digest-libapparmor-2.0_p6288 259
SHA256 ae7d5dd76d792a1ff7ee7817846dff1402573c7fee7b19a45120086dac49e898 files/digest-libapparmor-2.0_p6288 259

View File

@ -0,0 +1,3 @@
MD5 e7f5e6f8663919d5998469e842442509 libapparmor-2.0-6288.tar.gz 20725
RMD160 5f4b8a443a23d4cd4a16b35ae8ebf65647683b2e libapparmor-2.0-6288.tar.gz 20725
SHA256 0aebaae48f1917a65c43683ad8f332301fcf46d4dcb392177a4750b245f42882 libapparmor-2.0-6288.tar.gz 20725

View File

@ -0,0 +1,38 @@
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
inherit eutils toolchain-funcs
MY_P="${P/_p/-}"
DESCRIPTION="Primary support library and headers for AppArmor userspace"
HOMEPAGE="http://forge.novell.com/modules/xfmod/project/?apparmor"
SRC_URI="http://forge.novell.com/modules/xfcontent/private.php/apparmor/Development%20-%20April%20Snapshot/${MY_P}.tar.gz"
LICENSE="LGPL-2.1"
SLOT="0"
KEYWORDS="~x86"
IUSE=""
DEPEND="virtual/libc"
RDEPEND="${DEPEND}"
MY_S=${WORKDIR}/${P/_*/}
src_unpack() {
unpack ${A}
cd ${MY_S}
# the Make.rules isn't needed for Gentoo
sed -i "s/^include Make.rules//g" Makefile
}
src_compile() {
cd ${MY_S}
emake CC="$(tc-getCC)" CFLAGS="${CFLAGS}" || die
}
src_install() {
cd ${MY_S}
make DESTDIR="${D}" install || die
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE pkgmetadata SYSTEM "http://www.gentoo.org/dtd/metadata.dtd">
<pkgmetadata>
<herd>maintainer-wanted</herd>
</pkgmetadata>