
#
# Copyright (c) 2002, 2006, Oracle. All rights reserved.  
#
#    NAME
#      executestack.pl
#
#    DESCRIPTION
#      Get status of kernel parameter that indicates execute stack limitations
#
#    MODIFIED   (MM/DD/YY)
#    Howard sradhakr  09/07/06 - Backport sradhakr_bug-5390898 from main
#    Howard dsukhwal  12/09/05 - Backport dsukhwal_bug-4754359 from main 
#    Howard dsukhwal  11/30/05 - use execshield 
#    Howard dkjain    05/11/05 - 
#    Howard hmulling  03/16/04 - replace uname with perl command for windows 
#    Howard hmulling  03/16/04 - replace uname with perl command for windows 
#    Howard mbhoopat  03/10/04 - linux port 
#    Howard hmulling  12/09/03 - hmulling_bug-3284610 
#    Howard hmulling  12/09/03 - work on regexp 
#    Howard hmulling  12/09/03 - more fixes 
#    Howard Mullings  12/02/03 - add check for sparc 64 
#    Howard Mullings  12/01/03 - change name of the output property 
#    Howard Mullings  11/26/03 - created
#
#
# Summary
#
#	Print out status of kernel parameter that limits execution on the stack 
#
# Implementation
#	
#	1. Go through /etc/system and look for parameter to disable 
#          exection on the stack
#	2. Print executestack : "em_result=execute_statck=true|false"

#
# By default we assume that execution on the stack is allowed.
# See http://docs.sun.com/db/doc/816-7137/6md5pauis?noexec_user_stack&a=view
# By default a 64-bit kernel will not allow a 64-bit app to execute
# code on the user stack. The /etc/system parameter is used to determine
# if a 64-bit or 32-bit kernel will allow a 32-bit app to execute
# code on the user stack.
#
$ENV{PATH} = "$ENV{PATH}:/usr/bin:/usr/sbin:/usr/ucb:/sbin:/usr/local/sbin";

#
# By default we assume that execution on the stack is allowed.
# See http://docs.sun.com/db/doc/816-7137/6md5pauis?noexec_user_stack&a=view
# By default a 64-bit kernel will not allow a 64-bit app to execute
# code on the user stack. The /etc/system parameter is used to determine
# if a 64-bit or 32-bit kernel will allow a 32-bit app to execute
# code on the user stack.
#

#require "$ENV{EMDROOT}/sysman/admin/scripts/esa_config.pl";
#my $targetType = "host" ;
my $maxCount = $ENV{SMAXCOUNT};
$executestack = 'enabled';

if($maxCount == -1){
   $maxCount = 1 ;
}

chomp($os = $^O);
if (($os ne "MSWin32") && ($os ne "MSWin64")) 
{
	chomp($os = `uname -s`);
}
if ($os eq "Linux")
{
    if($maxCount > 0){
     my $cmd = 'sysctl -a | grep kernel.exec-shield';
     my $enable = 0;
     unless (open(SYS, "$cmd |")){
        print "em_error=Cannot run sysctl\n";
        exit(0);
     }
     while(<SYS>){
        chomp;
        if(m/(\s*)kernel.exec-shield(\s*)=(\s*)(.*)/i){
            $enable = $4;
        }
     }
     if( ($enable == 1) || ($enable == 2) ){
        print "em_result=execute_stack=disabled\n";
     }
     else{
        print "em_result=execute_stack=$executestack\n";
     }
    }
    exit(0);
}

if ($os eq "OSF1")
{
    $cmdout = `/sbin/sysconfig -q proc executable_stack | tail +2`;
    ($ignore, $value) = split('=', $cmdout);
    if ($value == 0)
    {
        $executestack = 'disabled';
    }
    if($maxCount > 0){
     print "em_result=execute_stack=$executestack\n";
    }
    exit(0);
}

if ($os eq "HP-UX")
{
    # Get the executable_stack kernel parameter and check it's
    # current value. The valid values are 0, 1, and 2, where
    #
    # 0 causes stacks to be non-executable
    # 1 causes all program stacks to be executable
    # 2 is equivalent to a setting of 0, except that it gives
    #   non-fatal warnings instead of terminating a process
    #
    # From the EM perspective, the following rules apply:
    #
    # 0,2 => return 'disabled'
    #   1 => return 'enabled'
    #
    my $nval = `kmtune -l -q executable_stack | grep ^Current:`;
    if ($nval =~ /Current:\s*(\d)/)
    {
        $executestack = "disabled" if ($1 == 0 || $1 == 2);
    }

    if($maxCount > 0){
      print "em_result=execute_stack=$executestack\n";
    }
    exit (0);
}

while (($_ = &Getline2('/etc/system'), $getline_ok)) {
    if ($_ =~ '^\s*set\s+noexec_user_stack\s*=\s*1($|\s|\*)') {
	$executestack = 'disabled';
    }
}
delete $opened{'/etc/system'} && close('/etc/system');

if($maxCount > 0){
  print "em_result=execute_stack=$executestack\n";
}

sub Getline2 {
    &Pick('',@_);
    if ($getline_ok = (($_ = <$fh>) ne '')) {
	chomp;	# strip record separator
    }
    $_;
}

sub Pick {
    local($mode,$name,$pipe) = @_;
    $fh = $name;
    open($name,$mode.$name.$pipe) unless $opened{$name}++;
}
