Linux Archive

Linux Archive (http://www.linux-archive.org/)
-   Ubuntu Kernel Team (http://www.linux-archive.org/ubuntu-kernel-team/)
-   -   UBUNTU: config-check -- add a configuration enforcer (http://www.linux-archive.org/ubuntu-kernel-team/293460-ubuntu-config-check-add-configuration-enforcer.html)

Andy Whitcroft 12-10-2009 04:41 PM

UBUNTU: config-check -- add a configuration enforcer
 
Add a new configuration option value checker and enforcer. This allow
us to specify the values we expect various configuration options to have
and to do that depending on the architecture and flavour of the build.
This is applied both as an early build check and at updateconfigs time.

Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
debian.master/config/enforce | 25 +++++
debian.master/rules.d/2-binary-arch.mk | 2 +-
debian.master/rules.d/4-checks.mk | 8 ++
debian.master/scripts/config-check | 168 +++++++++++++++++++++++++++++++
debian.master/scripts/misc/kernelconfig | 25 +++++-
5 files changed, 226 insertions(+), 2 deletions(-)
create mode 100644 debian.master/config/enforce
create mode 100755 debian.master/scripts/config-check

diff --git a/debian.master/config/enforce b/debian.master/config/enforce
new file mode 100644
index 0000000..605ab65
--- /dev/null
+++ b/debian.master/config/enforce
@@ -0,0 +1,25 @@
+#
+# SECURITY items
+#
+# Ensure this option is enabled.
+value CONFIG_COMPAT_BRK n
+value CONFIG_DEVKMEM n
+value CONFIG_LSM_MMAP_MIN_ADDR 0
+value CONFIG_SECCOMP y
+value CONFIG_SECURITY y
+value CONFIG_SECURITY_FILE_CAPABILITIES y
+value CONFIG_SECURITY_SMACK y
+value CONFIG_SYN_COOKIES y
+# For architectures which support this option ensure it is enabled.
+!exists CONFIG_CC_STACKPROTECTOR | value CONFIG_CC_STACKPROTECTOR y
+!exists CONFIG_DEBUG_RODATA | value CONFIG_DEBUG_RODATA y
+!exists CONFIG_STRICT_DEVMEM | value CONFIG_STRICT_DEVMEM y
+# For architectures which support this option ensure it is disabled.
+!exists CONFIG_COMPAT_VDSO | value CONFIG_COMPAT_VDSO n
+# Default to 32768 for armel, 65536 for everything else.
+(( arch armel | arch sparc ) & value CONFIG_DEFAULT_MMAP_MIN_ADDR 32768 ) |
+ ( value CONFIG_DEFAULT_MMAP_MIN_ADDR 65536)
+
+# CONFIG_USB_DEVICE_FS breaks udev USB firmware loading and is deprecated
+# ensure it is disabled.
+value CONFIG_USB_DEVICEFS n
diff --git a/debian.master/rules.d/2-binary-arch.mk b/debian.master/rules.d/2-binary-arch.mk
index 4468d25..fb0d2a3 100644
--- a/debian.master/rules.d/2-binary-arch.mk
+++ b/debian.master/rules.d/2-binary-arch.mk
@@ -3,7 +3,7 @@

# Prepare the out-of-tree build directory

-prepare-%: $(stampdir)/stamp-prepare-%
+prepare-%: $(stampdir)/stamp-prepare-% prepare-checks-%
@# Empty for make to be happy
$(stampdir)/stamp-prepare-%: target_flavour = $*
$(stampdir)/stamp-prepare-%: $(commonconfdir)/config.common.$(family) $(archconfdir)/config.common.$(arch) $(archconfdir)/config.flavour.%
diff --git a/debian.master/rules.d/4-checks.mk b/debian.master/rules.d/4-checks.mk
index 778984c..093639e 100644
--- a/debian.master/rules.d/4-checks.mk
+++ b/debian.master/rules.d/4-checks.mk
@@ -24,3 +24,11 @@ module-check-%: $(abidir)/%.modules

checks-%: abi-check-% module-check-%
@# Will be calling more stuff later
+
+# Check the config against the known options list.
+config-prepare-check-%: $(stampdir)/stamp-prepare-%
+ @perl -f $(DEBIAN)/scripts/config-check
+ $(builddir)/build-$*/.config "$(arch)" "$*" "$(commonconfdir)" "$(skipconfig)"
+
+prepare-checks-%: config-prepare-check-%
+ @# Will be calling more stuff later
diff --git a/debian.master/scripts/config-check b/debian.master/scripts/config-check
new file mode 100755
index 0000000..e43465c
--- /dev/null
+++ b/debian.master/scripts/config-check
@@ -0,0 +1,168 @@
+#!/usr/bin/perl
+#
+# check-config -- check the current config for issues
+#
+use strict;
+
+my $P = 'check-config';
+
+if ($#ARGV != 4) {
+ die "Usage: $P <config> <arch> <flavour> <commonconfig> <warn-only>
";
+}
+
+my ($config, $arch, $flavour, $commonconfig, $warn_only) = @ARGV;
+
+my $checks = "$commonconfig/enforce";
+
+# If we are in overridden then still perform the checks and emit the messages
+# but do not return failure. Those items marked FATAL will alway trigger
+# failure.
+my $fail_exit = 1;
+$fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1');
+my $exit_val = 0;
+
+# Load up the current configuration values -- FATAL if this fails
+print "$P: $config: loading config
";
+my %values = ();
+open(CONFIG, "<$config") || die "$P: $config: open failed -- $! -- aborting
";
+while (<CONFIG>) {
+ # Pull out values.
+ /^#*s*(CONFIG_w+)[s=](.*)$/ or next;
+ if ($2 eq 'is not set') {
+ $values{$1} = 'n';
+ } else {
+ $values{$1} = $2;
+ }
+}
+close(CONFIG);
+
+# Predicate execution engine.
+sub pred_first {
+ my ($rest) = @_;
+ my $depth = 0;
+ my $char;
+ my $pred;
+
+ for ($char = 0; $char <= length($rest); $char++) {
+ if (substr($rest, $char, 1) eq '(') {
+ $depth++;
+ } elsif (substr($rest, $char, 1) eq ')') {
+ if (--$depth == 0) {
+ $char++;
+ last;
+ }
+ } elsif ($depth == 0 && substr($rest, $char, 1) eq '&') {
+ $char--;
+ last;
+ } elsif ($depth == 0 && substr($rest, $char, 1) eq '|') {
+ $char--;
+ last;
+ }
+ }
+ if ($depth != 0) {
+ die "$P: $rest: missing close parenthesis ')'
";
+ }
+
+ ($pred, $rest) = (substr($rest, 0, $char), substr($rest, $char + 1));
+
+ $pred =~ s/^s*(//;
+ $pred =~ s/)s*$//;
+ $pred =~ s/^s*//;
+ $pred =~ s/s*$//;
+
+ ($pred, $rest);
+}
+
+sub pred_do {
+ my ($pred) = @_;
+ my (@a) = split(' ', $pred);
+
+ if ($a[0] eq 'arch') {
+ die "$P: $pred: malformed -- $pred <arch>
" if ($#a != 1);
+ #print " *** ARCH<$arch ?? $a[1]>
";
+ return ($arch eq $a[1])
+ } elsif ($a[0] eq 'flavour') {
+ die "$P: $pred: malformed -- $pred <flavour>
" if ($#a != 1);
+ #print " *** FLAVOUR<$flavour ?? $a[1]>
";
+ return ($flavour eq $a[1])
+ } elsif ($a[0] eq 'value') {
+ die "$P: $pred: malformed -- $pred <name> <val>
" if ($#a != 2);
+ #print " *** CHECK<$a[1] $a[2] ?? " . $values{$a[1]} . ">
";
+ return ($values{$a[1]} eq $a[2]);
+ } elsif ($a[0] eq 'exists') {
+ die "$P: $pred: malformed -- $pred <name>
" if ($#a != 1);
+ return (defined $values{$a[1]});
+ } else {
+ die "$P: $pred: unknown predicate
";
+ }
+ return 1;
+}
+sub pred_exec {
+ my ($rest) = @_;
+ my $pred;
+ my $res;
+ my $res2;
+ my $invert = 0;
+
+ #print "pred_exec('$rest')
";
+
+ ($pred, $rest) = pred_first($rest);
+ if ($pred =~ /^s*!s*(.*)$/) {
+ ($pred, $invert) = ($1, 1);
+ }
+ if ($rest =~ /^s*$/) {
+ $res = pred_do($pred);
+ $res = !$res if ($invert);
+
+ } elsif ($rest =~ /^s*(||&)s*(.*)$/) {
+ my ($op, $right) = ($1, $2);
+
+ #print " *left<$pred> op<$op> right<$right>
";
+ $res = pred_exec($pred);
+ $res = !$res if ($invert);
+ if (($res && $op eq '&') || (!$res && $op eq '|')) {
+ #print " left<$pred> op<$op> *right<$right>
";
+ $res = pred_exec($right);
+ }
+
+ } else {
+ die "$P: $pred$rest: malformed predicate
";
+ }
+ #print "res<$rest> -> pred<$pred> rest<$rest>
";
+ return $res;
+}
+
+# FATAL: Check if we have an enforcement list.
+my $pass = 0;
+my $total = 0;
+my $line = ';
+print "$P: $checks: loading checks
";
+open(CHECKS, "<$checks") || die "$P: $checks: open failed -- $! -- aborting
";
+while (<CHECKS>) {
+ /^#/ && next;
+ chomp;
+
+ $line .= $_;
+ if ($line =~ /$/) {
+ chop($line);
+ $line .= " ";
+ next;
+ }
+ $line =~ /^s*$/ && next;
+
+ #print "CHECK: <$line>
";
+ $total++;
+ my $result = pred_exec($line);
+ if (!$result) {
+ print "$P: FAIL: $line
";
+ $exit_val = $fail_exit;
+ } else {
+ $pass++;
+ }
+
+ $line = ';
+}
+close(CHECKS);
+
+print "$P: $pass/$total checks passed -- exit $exit_val
";
+exit $exit_val;
diff --git a/debian.master/scripts/misc/kernelconfig b/debian.master/scripts/misc/kernelconfig
index 4bf7c1d..c01624e 100755
--- a/debian.master/scripts/misc/kernelconfig
+++ b/debian.master/scripts/misc/kernelconfig
@@ -116,7 +116,6 @@ for arch in $archs; do
done

rm -f $common_conf
-rm -rf build

# Now run splitconfig.pl on all the config.common.<arch> copied to
# $tmpdir
@@ -130,3 +129,27 @@ rm -rf build
>$arch/config.common.$arch
done
)
+
+echo ""
+echo "Running config-check for all configurations ..."
+echo ""
+fail=0
+for arch in $archs; do
+ archconfdir=$confdir/$arch
+ flavourconfigs=$(cd $archconfdir && ls config.flavour.*)
+ for config in $flavourconfigs; do
+ if [ -f $archconfdir/$config ]; then
+ fullconf="$tmpdir/$arch-$config-full"
+ "$bindir/../config-check" "$fullconf" "$arch" "$config" "$confdir" "0" || let "fail=$fail+1"
+ fi
+ done
+done
+
+if [ "$fail" != 0 ]; then
+ echo ""
+ echo "*** ERROR: $fail config-check failures detected"
+ echo ""
+fi
+
+rm -rf build
+
--
1.6.3.3


--
kernel-team mailing list
kernel-team@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/kernel-team

Andy Whitcroft 12-15-2009 04:19 PM

UBUNTU: config-check -- add a configuration enforcer
 
Add a new configuration option value checker and enforcer. This allow
us to specify the values we expect various configuration options to have
and to do that depending on the architecture and flavour of the build.
This is applied both as an early build check and at updateconfigs time.

Signed-off-by: Andy Whitcroft <apw@canonical.com>
---
debian.master/config/enforce | 25 ++++
debian.master/rules.d/2-binary-arch.mk | 2 +-
debian.master/rules.d/4-checks.mk | 8 ++
debian.master/scripts/config-check | 187 +++++++++++++++++++++++++++++++
debian.master/scripts/misc/kernelconfig | 25 ++++-
5 files changed, 245 insertions(+), 2 deletions(-)
create mode 100644 debian.master/config/enforce
create mode 100755 debian.master/scripts/config-check

diff --git a/debian.master/config/enforce b/debian.master/config/enforce
new file mode 100644
index 0000000..605ab65
--- /dev/null
+++ b/debian.master/config/enforce
@@ -0,0 +1,25 @@
+#
+# SECURITY items
+#
+# Ensure this option is enabled.
+value CONFIG_COMPAT_BRK n
+value CONFIG_DEVKMEM n
+value CONFIG_LSM_MMAP_MIN_ADDR 0
+value CONFIG_SECCOMP y
+value CONFIG_SECURITY y
+value CONFIG_SECURITY_FILE_CAPABILITIES y
+value CONFIG_SECURITY_SMACK y
+value CONFIG_SYN_COOKIES y
+# For architectures which support this option ensure it is enabled.
+!exists CONFIG_CC_STACKPROTECTOR | value CONFIG_CC_STACKPROTECTOR y
+!exists CONFIG_DEBUG_RODATA | value CONFIG_DEBUG_RODATA y
+!exists CONFIG_STRICT_DEVMEM | value CONFIG_STRICT_DEVMEM y
+# For architectures which support this option ensure it is disabled.
+!exists CONFIG_COMPAT_VDSO | value CONFIG_COMPAT_VDSO n
+# Default to 32768 for armel, 65536 for everything else.
+(( arch armel | arch sparc ) & value CONFIG_DEFAULT_MMAP_MIN_ADDR 32768 ) |
+ ( value CONFIG_DEFAULT_MMAP_MIN_ADDR 65536)
+
+# CONFIG_USB_DEVICE_FS breaks udev USB firmware loading and is deprecated
+# ensure it is disabled.
+value CONFIG_USB_DEVICEFS n
diff --git a/debian.master/rules.d/2-binary-arch.mk b/debian.master/rules.d/2-binary-arch.mk
index e6bba87..d909d89 100644
--- a/debian.master/rules.d/2-binary-arch.mk
+++ b/debian.master/rules.d/2-binary-arch.mk
@@ -3,7 +3,7 @@

# Prepare the out-of-tree build directory

-prepare-%: $(stampdir)/stamp-prepare-%
+prepare-%: $(stampdir)/stamp-prepare-% prepare-checks-%
@# Empty for make to be happy
$(stampdir)/stamp-prepare-%: target_flavour = $*
$(stampdir)/stamp-prepare-%: $(commonconfdir)/config.common.$(family) $(archconfdir)/config.common.$(arch) $(archconfdir)/config.flavour.%
diff --git a/debian.master/rules.d/4-checks.mk b/debian.master/rules.d/4-checks.mk
index 778984c..093639e 100644
--- a/debian.master/rules.d/4-checks.mk
+++ b/debian.master/rules.d/4-checks.mk
@@ -24,3 +24,11 @@ module-check-%: $(abidir)/%.modules

checks-%: abi-check-% module-check-%
@# Will be calling more stuff later
+
+# Check the config against the known options list.
+config-prepare-check-%: $(stampdir)/stamp-prepare-%
+ @perl -f $(DEBIAN)/scripts/config-check
+ $(builddir)/build-$*/.config "$(arch)" "$*" "$(commonconfdir)" "$(skipconfig)"
+
+prepare-checks-%: config-prepare-check-%
+ @# Will be calling more stuff later
diff --git a/debian.master/scripts/config-check b/debian.master/scripts/config-check
new file mode 100755
index 0000000..48409f7
--- /dev/null
+++ b/debian.master/scripts/config-check
@@ -0,0 +1,187 @@
+#!/usr/bin/perl
+#
+# check-config -- check the current config for issues
+#
+use strict;
+
+my $P = 'check-config';
+
+if ($#ARGV != 4) {
+ die "Usage: $P <config> <arch> <flavour> <commonconfig> <warn-only>
";
+}
+
+my ($config, $arch, $flavour, $commonconfig, $warn_only) = @ARGV;
+
+my $checks = "$commonconfig/enforce";
+my %values = ();
+
+# If we are in overridden then still perform the checks and emit the messages
+# but do not return failure. Those items marked FATAL will alway trigger
+# failure.
+my $fail_exit = 1;
+$fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1');
+my $exit_val = 0;
+
+# Predicate execution engine.
+sub pred_first {
+ my ($rest) = @_;
+ my $depth = 0;
+ my $off;
+ my $char;
+ my $pred;
+
+ for ($off = 0; $off <= length($rest); $off++) {
+ $char = substr($rest, $off, 1);
+ if ($char eq '(') {
+ $depth++;
+ } elsif ($char eq ')') {
+ $depth--;
+ } elsif ($depth == 0 && $char eq '&') {
+ last;
+ } elsif ($depth == 0 && $char eq '|') {
+ last;
+ }
+ }
+ if ($depth > 0) {
+ die "$P: $rest: missing close parenthesis ')'
";
+ } elsif ($depth < 0) {
+ die "$P: $rest: missing open parenthesis '('
";
+ }
+
+ ($pred, $rest) = (substr($rest, 0, $off), substr($rest, $off + 1));
+
+ $pred =~ s/^s*//;
+ $pred =~ s/s*$//;
+
+ #print "pred<$pred> rest<$rest> char<$char>
";
+ ($pred, $rest, $char);
+}
+
+sub pred_do {
+ my ($pred) = @_;
+ my (@a) = split(' ', $pred);
+
+ if ($a[0] eq 'arch') {
+ die "$P: $pred: malformed -- $pred <arch>
" if ($#a != 1);
+ #print " *** ARCH<$arch ?? $a[1]>
";
+ return ($arch eq $a[1])
+ } elsif ($a[0] eq 'flavour') {
+ die "$P: $pred: malformed -- $pred <flavour>
" if ($#a != 1);
+ #print " *** FLAVOUR<$flavour ?? $a[1]>
";
+ return ($flavour eq $a[1])
+ } elsif ($a[0] eq 'value') {
+ die "$P: $pred: malformed -- $pred <name> <val>
" if ($#a != 2);
+ #print " *** CHECK<$a[1] $a[2] ?? " . $values{$a[1]} . ">
";
+ return ($values{$a[1]} eq $a[2]);
+ } elsif ($a[0] eq 'exists') {
+ die "$P: $pred: malformed -- $pred <name>
" if ($#a != 1);
+ return (defined $values{$a[1]});
+ } else {
+ die "$P: $pred: unknown predicate
";
+ }
+ return 1;
+}
+sub pred_exec {
+ my ($rest) = @_;
+ my $pred;
+ my $res;
+ my $sep;
+
+ #print "pred_exec<$rest>
";
+
+ ($pred, $rest, $sep) = pred_first($rest);
+
+ # Leading ! implies inversion.
+ if ($pred =~ /^s*!s*(.*)$/) {
+ #print " invert<$1>
";
+ $res = !pred_exec($1);
+
+ # Recurse left for complex expressions.
+ } elsif ($pred =~ /^s*((.*))s*$/) {
+ #print " left<$1>
";
+ $res = pred_exec($1);
+
+ # Check for common syntax issues.
+ } elsif ($pred eq ') {
+ if ($sep eq '&' || $sep eq '|') {
+ die "$P: $pred$rest: malformed binary operator
";
+ } else {
+ die "$P: $pred$rest: syntax error
";
+ }
+
+ # A predicate, execute it.
+ } else {
+ #print " DO<$pred> sep<$sep>
";
+ $res = pred_do($pred);
+ }
+
+ #print " pre-return res<$res> sep<$sep>
";
+ if ($sep eq ') {
+ #
+
+ # Recurse right for binary operators -- note these are lazy.
+ } elsif ($sep eq '&' || $sep eq '|') {
+ #print " right<$rest> ? sep<$sep> res<$res>
";
+ if ($rest =~ /^s*($|||&)/) {
+ die "$P: $pred$rest: malformed binary operator
";
+ }
+ if (($res && $sep eq '&') || (!$res && $sep eq '|')) {
+ #print " right<$rest>
";
+ $res = pred_exec($rest);
+ }
+
+ } else {
+ die "$P: $pred$rest: malformed predicate
";
+ }
+ #print " return res<$res> sep<$sep>
";
+ return $res;
+}
+
+# Load up the current configuration values -- FATAL if this fails
+print "$P: $config: loading config
";
+open(CONFIG, "<$config") || die "$P: $config: open failed -- $! -- aborting
";
+while (<CONFIG>) {
+ # Pull out values.
+ /^#*s*(CONFIG_w+)[s=](.*)$/ or next;
+ if ($2 eq 'is not set') {
+ $values{$1} = 'n';
+ } else {
+ $values{$1} = $2;
+ }
+}
+close(CONFIG);
+
+# FATAL: Check if we have an enforcement list.
+my $pass = 0;
+my $total = 0;
+my $line = ';
+print "$P: $checks: loading checks
";
+open(CHECKS, "<$checks") || die "$P: $checks: open failed -- $! -- aborting
";
+while (<CHECKS>) {
+ /^#/ && next;
+ chomp;
+
+ $line .= $_;
+ if ($line =~ /$/) {
+ chop($line);
+ $line .= " ";
+ next;
+ }
+ $line =~ /^s*$/ && next;
+
+ #print "CHECK: <$line>
";
+ $total++;
+ my $result = pred_exec($line);
+ if (!$result) {
+ print "$P: FAIL: $line
";
+ $exit_val = $fail_exit;
+ } else {
+ $pass++;
+ }
+
+ $line = ';
+}
+close(CHECKS);
+
+print "$P: $pass/$total checks passed -- exit $exit_val
";
+exit $exit_val;
diff --git a/debian.master/scripts/misc/kernelconfig b/debian.master/scripts/misc/kernelconfig
index 4bf7c1d..c01624e 100755
--- a/debian.master/scripts/misc/kernelconfig
+++ b/debian.master/scripts/misc/kernelconfig
@@ -116,7 +116,6 @@ for arch in $archs; do
done

rm -f $common_conf
-rm -rf build

# Now run splitconfig.pl on all the config.common.<arch> copied to
# $tmpdir
@@ -130,3 +129,27 @@ rm -rf build
>$arch/config.common.$arch
done
)
+
+echo ""
+echo "Running config-check for all configurations ..."
+echo ""
+fail=0
+for arch in $archs; do
+ archconfdir=$confdir/$arch
+ flavourconfigs=$(cd $archconfdir && ls config.flavour.*)
+ for config in $flavourconfigs; do
+ if [ -f $archconfdir/$config ]; then
+ fullconf="$tmpdir/$arch-$config-full"
+ "$bindir/../config-check" "$fullconf" "$arch" "$config" "$confdir" "0" || let "fail=$fail+1"
+ fi
+ done
+done
+
+if [ "$fail" != 0 ]; then
+ echo ""
+ echo "*** ERROR: $fail config-check failures detected"
+ echo ""
+fi
+
+rm -rf build
+
--
1.6.3.3


--
kernel-team mailing list
kernel-team@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/kernel-team

Stefan Bader 12-16-2009 03:42 PM

UBUNTU: config-check -- add a configuration enforcer
 
Ok, yeah. I now see some code to make it go down both
sides of logical operators and also descent into
multiple layers of braces. The handling of & and |
is nice.

-Stefan

--
kernel-team mailing list
kernel-team@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/kernel-team


All times are GMT. The time now is 02:37 PM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.