Initial Import of Matthew Snelham <zeypher@sigalrm.com> Apparmor ebuilds
This commit is contained in:
parent
2835e5b1d7
commit
57b6d1ece8
10
trunk/novell4gentoo/sec-policy/apparmor-profiles/ChangeLog
Normal file
10
trunk/novell4gentoo/sec-policy/apparmor-profiles/ChangeLog
Normal 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
|
||||||
|
|
@ -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
|
@ -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
|
||||||
|
}
|
@ -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
|
@ -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>
|
11
trunk/novell4gentoo/sys-apps/apparmor/ChangeLog
Normal file
11
trunk/novell4gentoo/sys-apps/apparmor/ChangeLog
Normal 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
|
||||||
|
|
30
trunk/novell4gentoo/sys-apps/apparmor/Manifest
Normal file
30
trunk/novell4gentoo/sys-apps/apparmor/Manifest
Normal 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
|
8
trunk/novell4gentoo/sys-apps/apparmor/TODO
Normal file
8
trunk/novell4gentoo/sys-apps/apparmor/TODO
Normal 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
|
118
trunk/novell4gentoo/sys-apps/apparmor/apparmor-2.0.ebuild
Normal file
118
trunk/novell4gentoo/sys-apps/apparmor/apparmor-2.0.ebuild
Normal 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
|
||||||
|
}
|
40
trunk/novell4gentoo/sys-apps/apparmor/files/aaeventd
Executable file
40
trunk/novell4gentoo/sys-apps/apparmor/files/aaeventd
Executable 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
|
||||||
|
}
|
56
trunk/novell4gentoo/sys-apps/apparmor/files/apparmor
Executable file
56
trunk/novell4gentoo/sys-apps/apparmor/files/apparmor
Executable 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 $?
|
||||||
|
}
|
@ -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
|
443
trunk/novell4gentoo/sys-apps/apparmor/files/rc.apparmor.functions
Executable file
443
trunk/novell4gentoo/sys-apps/apparmor/files/rc.apparmor.functions
Executable 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
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
5
trunk/novell4gentoo/sys-apps/apparmor/metadata.xml
Normal file
5
trunk/novell4gentoo/sys-apps/apparmor/metadata.xml
Normal 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>
|
23
trunk/novell4gentoo/sys-kernel/apparmor-sources/ChangeLog
Normal file
23
trunk/novell4gentoo/sys-kernel/apparmor-sources/ChangeLog
Normal 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
|
||||||
|
|
73
trunk/novell4gentoo/sys-kernel/apparmor-sources/Manifest
Normal file
73
trunk/novell4gentoo/sys-kernel/apparmor-sources/Manifest
Normal 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
|
@ -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."
|
||||||
|
}
|
@ -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."
|
||||||
|
}
|
@ -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/
|
@ -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/
|
@ -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/
|
File diff suppressed because it is too large
Load Diff
@ -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/
|
@ -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/
|
@ -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/
|
@ -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/
|
@ -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/
|
@ -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(¤t->fs->lock);
|
||||||
|
- rootmnt = mntget(current->fs->rootmnt);
|
||||||
|
- root = dget(current->fs->root);
|
||||||
|
- read_unlock(¤t->fs->lock);
|
||||||
|
+ if (!(flags & DPATH_SYSROOT)){
|
||||||
|
+ read_lock(¤t->fs->lock);
|
||||||
|
+ rootmnt = mntget(current->fs->rootmnt);
|
||||||
|
+ root = dget(current->fs->root);
|
||||||
|
+ read_unlock(¤t->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/
|
@ -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/
|
@ -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);
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
@ -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
|
@ -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
|
@ -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>
|
10
trunk/novell4gentoo/sys-libs/libapparmor/ChangeLog
Normal file
10
trunk/novell4gentoo/sys-libs/libapparmor/ChangeLog
Normal 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
|
||||||
|
|
8
trunk/novell4gentoo/sys-libs/libapparmor/Manifest
Normal file
8
trunk/novell4gentoo/sys-libs/libapparmor/Manifest
Normal 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
|
@ -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
|
@ -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
|
||||||
|
}
|
5
trunk/novell4gentoo/sys-libs/libapparmor/metadata.xml
Normal file
5
trunk/novell4gentoo/sys-libs/libapparmor/metadata.xml
Normal 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>
|
Loading…
Reference in New Issue
Block a user