3
# $Id: genprof 458 2007-03-20 22:58:38Z jmichael-at-suse-de $
5
# ----------------------------------------------------------------------
6
# Copyright (c) 2005 Novell, Inc. All Rights Reserved.
8
# This program is free software; you can redistribute it and/or
9
# modify it under the terms of version 2 of the GNU General Public
10
# License as published by the Free Software Foundation.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
# GNU General Public License for more details.
17
# You should have received a copy of the GNU General Public License
18
# along with this program; if not, contact Novell, Inc.
20
# To contact Novell about this file by physical or electronic mail,
21
# you may find current contact information at www.novell.com.
22
# ----------------------------------------------------------------------
27
use Immunix::SubDomain;
34
# force $PATH to be sane
35
$ENV{PATH} = "/bin:/sbin:/usr/bin:/usr/sbin";
37
# initialize the local poo
38
setlocale(LC_MESSAGES, "");
39
textdomain("apparmor-utils");
45
'file|f=s' => \$filename,
46
'dir|d=s' => \$profiledir,
50
# tell 'em how to use it...
51
&usage && exit if $help;
53
my $sd_mountpoint = check_for_subdomain();
54
unless ($sd_mountpoint) {
55
fatal_error(gettext("SubDomain does not appear to be started. Please enable SubDomain and try again."));
58
# let's convert it to full path...
59
$profiledir = get_full_path($profiledir);
61
unless (-d $profiledir) {
62
fatal_error "Can't find subdomain profiles in $profiledir.";
65
# what are we profiling?
66
my $profiling = shift;
69
$profiling = UI_GetString(gettext("Please enter the program to profile: "), "")
75
$fqdbin = get_full_path($profiling);
78
if ($profiling !~ /\//) {
79
my $which = which($profiling);
81
$fqdbin = get_full_path($which);
86
unless ($fqdbin && -e $fqdbin) {
87
if ($profiling =~ /^[^\/]+$/) {
88
fatal_error(sprintf(gettext('Can\'t find %s in the system path list. If the name of the application is correct, please run \'which %s\' in the other window in order to find the fully-qualified path.'), $profiling, $profiling));
90
fatal_error(sprintf(gettext('%s does not exist, please double-check the path.'), $profiling));
94
# read the settings in /etc/logprof.conf
97
# make sure that the app they're requesting to profile is not marked as
98
# not allowed to have it's own profile
99
if ($qualifiers{$fqdbin}) {
100
unless ($qualifiers{$fqdbin} =~ /p/) {
101
fatal_error(sprintf(gettext("\%s is currently marked as a program that should not have it's own profile. Usually, programs are marked this way if creating a profile for them is likely to break the rest of the system. If you know what you're doing and are certain you want to create a profile for this program, edit the corresponding entry in the [qualifiers] section in /etc/apparmor/logprof.conf."), $fqdbin));
105
# load all the include files
108
my $profilefilename = getprofilefilename($fqdbin);
109
if (-e $profilefilename) {
110
$helpers{$fqdbin} = getprofileflags($profilefilename) || "enforce";
113
$helpers{$fqdbin} = "enforce";
116
if ($helpers{$fqdbin} eq "enforce") {
121
UI_Important(gettext("Please start the application to be profiled in \nanother window and exercise its functionality now.\n\nOnce completed, select the \"Scan\" button below in \norder to scan the system logs for AppArmor events. \n\nFor each AppArmor event, you will be given the \nopportunity to choose whether the access should be \nallowed or denied."));
125
my $done_profiling = 0;
127
$syslog = 0 if (-e "/var/log/audit/audit.log");
129
while (not $done_profiling) {
131
$logmark = `date | md5sum`;
133
$logmark = $1 if $logmark =~ /^([0-9a-f]+)/;
134
system("/bin/logger -p kern.warn 'GenProf: $logmark'");
136
$logmark = last_audit_entry_time();
140
$q->{headers} = [ gettext("Profiling"), $fqdbin ];
141
$q->{functions} = [ "CMD_SCAN", "CMD_FINISHED" ];
142
$q->{default} = "CMD_SCAN";
144
my ($ans, $arg) = UI_PromptUser($q);
146
if ($ans eq "CMD_SCAN") {
148
my $lp_ret = do_logprof_pass($logmark);
150
$done_profiling = 1 if $lp_ret eq "FINISHED";
160
for my $p (sort keys %helpers) {
161
if ($helpers{$p} eq "enforce") {
167
UI_Info(gettext("Reloaded SubDomain profiles in enforce mode."));
168
UI_Info(sprintf(gettext('Finished generating profile for %s.'), $fqdbin));
172
UI_Info(sprintf(gettext("usage: \%s [ -d /path/to/profiles ] [ -f /path/to/logfile ] [ program to profile ]"), $0));
176
sub last_audit_entry_time {
177
local $_ = `tail -1 /var/log/audit/audit.log`;
179
if (/^*msg\=audit\((\d+\.\d+\:\d+).*\).*$/) {