aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/get_maintainer.pl499
-rw-r--r--scripts/kconfig/mconf.c2
-rwxr-xr-xscripts/kernel-doc15
-rw-r--r--scripts/mod/file2alias.c95
-rwxr-xr-xscripts/recordmcount.pl222
-rw-r--r--scripts/selinux/Makefile4
-rw-r--r--scripts/selinux/genheaders/.gitignore1
-rw-r--r--scripts/selinux/genheaders/Makefile5
-rw-r--r--scripts/selinux/genheaders/genheaders.c118
-rw-r--r--scripts/selinux/mdp/mdp.c151
10 files changed, 743 insertions, 369 deletions
diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl
index 81a67a458e78..445e8845f0a4 100755
--- a/scripts/get_maintainer.pl
+++ b/scripts/get_maintainer.pl
@@ -13,7 +13,7 @@
13use strict; 13use strict;
14 14
15my $P = $0; 15my $P = $0;
16my $V = '0.21'; 16my $V = '0.23';
17 17
18use Getopt::Long qw(:config no_auto_abbrev); 18use Getopt::Long qw(:config no_auto_abbrev);
19 19
@@ -23,16 +23,19 @@ my $email_usename = 1;
23my $email_maintainer = 1; 23my $email_maintainer = 1;
24my $email_list = 1; 24my $email_list = 1;
25my $email_subscriber_list = 0; 25my $email_subscriber_list = 0;
26my $email_git = 1;
27my $email_git_penguin_chiefs = 0; 26my $email_git_penguin_chiefs = 0;
27my $email_git = 1;
28my $email_git_blame = 0;
28my $email_git_min_signatures = 1; 29my $email_git_min_signatures = 1;
29my $email_git_max_maintainers = 5; 30my $email_git_max_maintainers = 5;
30my $email_git_min_percent = 5; 31my $email_git_min_percent = 5;
31my $email_git_since = "1-year-ago"; 32my $email_git_since = "1-year-ago";
32my $email_git_blame = 0; 33my $email_hg_since = "-365";
33my $email_remove_duplicates = 1; 34my $email_remove_duplicates = 1;
34my $output_multiline = 1; 35my $output_multiline = 1;
35my $output_separator = ", "; 36my $output_separator = ", ";
37my $output_roles = 0;
38my $output_rolestats = 0;
36my $scm = 0; 39my $scm = 0;
37my $web = 0; 40my $web = 0;
38my $subsystem = 0; 41my $subsystem = 0;
@@ -64,21 +67,52 @@ my $penguin_chiefs = "\(" . join("|",@penguin_chief_names) . "\)";
64my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])"; 67my $rfc822_lwsp = "(?:(?:\\r\\n)?[ \\t])";
65my $rfc822_char = '[\\000-\\377]'; 68my $rfc822_char = '[\\000-\\377]';
66 69
70# VCS command support: class-like functions and strings
71
72my %VCS_cmds;
73
74my %VCS_cmds_git = (
75 "execute_cmd" => \&git_execute_cmd,
76 "available" => '(which("git") ne "") && (-d ".git")',
77 "find_signers_cmd" => "git log --since=\$email_git_since -- \$file",
78 "find_commit_signers_cmd" => "git log -1 \$commit",
79 "blame_range_cmd" => "git blame -l -L \$diff_start,+\$diff_length \$file",
80 "blame_file_cmd" => "git blame -l \$file",
81 "commit_pattern" => "^commit [0-9a-f]{40,40}",
82 "blame_commit_pattern" => "^([0-9a-f]+) "
83);
84
85my %VCS_cmds_hg = (
86 "execute_cmd" => \&hg_execute_cmd,
87 "available" => '(which("hg") ne "") && (-d ".hg")',
88 "find_signers_cmd" =>
89 "hg log --date=\$email_hg_since" .
90 " --template='commit {node}\\n{desc}\\n' -- \$file",
91 "find_commit_signers_cmd" => "hg log --template='{desc}\\n' -r \$commit",
92 "blame_range_cmd" => "", # not supported
93 "blame_file_cmd" => "hg blame -c \$file",
94 "commit_pattern" => "^commit [0-9a-f]{40,40}",
95 "blame_commit_pattern" => "^([0-9a-f]+):"
96);
97
67if (!GetOptions( 98if (!GetOptions(
68 'email!' => \$email, 99 'email!' => \$email,
69 'git!' => \$email_git, 100 'git!' => \$email_git,
101 'git-blame!' => \$email_git_blame,
70 'git-chief-penguins!' => \$email_git_penguin_chiefs, 102 'git-chief-penguins!' => \$email_git_penguin_chiefs,
71 'git-min-signatures=i' => \$email_git_min_signatures, 103 'git-min-signatures=i' => \$email_git_min_signatures,
72 'git-max-maintainers=i' => \$email_git_max_maintainers, 104 'git-max-maintainers=i' => \$email_git_max_maintainers,
73 'git-min-percent=i' => \$email_git_min_percent, 105 'git-min-percent=i' => \$email_git_min_percent,
74 'git-since=s' => \$email_git_since, 106 'git-since=s' => \$email_git_since,
75 'git-blame!' => \$email_git_blame, 107 'hg-since=s' => \$email_hg_since,
76 'remove-duplicates!' => \$email_remove_duplicates, 108 'remove-duplicates!' => \$email_remove_duplicates,
77 'm!' => \$email_maintainer, 109 'm!' => \$email_maintainer,
78 'n!' => \$email_usename, 110 'n!' => \$email_usename,
79 'l!' => \$email_list, 111 'l!' => \$email_list,
80 's!' => \$email_subscriber_list, 112 's!' => \$email_subscriber_list,
81 'multiline!' => \$output_multiline, 113 'multiline!' => \$output_multiline,
114 'roles!' => \$output_roles,
115 'rolestats!' => \$output_rolestats,
82 'separator=s' => \$output_separator, 116 'separator=s' => \$output_separator,
83 'subsystem!' => \$subsystem, 117 'subsystem!' => \$subsystem,
84 'status!' => \$status, 118 'status!' => \$status,
@@ -90,8 +124,7 @@ if (!GetOptions(
90 'v|version' => \$version, 124 'v|version' => \$version,
91 'h|help' => \$help, 125 'h|help' => \$help,
92 )) { 126 )) {
93 usage(); 127 die "$P: invalid argument - use --help if necessary\n";
94 die "$P: invalid argument\n";
95} 128}
96 129
97if ($help != 0) { 130if ($help != 0) {
@@ -113,6 +146,10 @@ if ($output_separator ne ", ") {
113 $output_multiline = 0; 146 $output_multiline = 0;
114} 147}
115 148
149if ($output_rolestats) {
150 $output_roles = 1;
151}
152
116my $selections = $email + $scm + $status + $subsystem + $web; 153my $selections = $email + $scm + $status + $subsystem + $web;
117if ($selections == 0) { 154if ($selections == 0) {
118 usage(); 155 usage();
@@ -175,7 +212,7 @@ if ($email_remove_duplicates) {
175 next if ($line =~ m/^\s*$/); 212 next if ($line =~ m/^\s*$/);
176 213
177 my ($name, $address) = parse_email($line); 214 my ($name, $address) = parse_email($line);
178 $line = format_email($name, $address); 215 $line = format_email($name, $address, $email_usename);
179 216
180 next if ($line =~ m/^\s*$/); 217 next if ($line =~ m/^\s*$/);
181 218
@@ -207,12 +244,10 @@ foreach my $file (@ARGV) {
207 push(@files, $file); 244 push(@files, $file);
208 if (-f $file && $keywords) { 245 if (-f $file && $keywords) {
209 open(FILE, "<$file") or die "$P: Can't open ${file}\n"; 246 open(FILE, "<$file") or die "$P: Can't open ${file}\n";
210 while (<FILE>) { 247 my $text = do { local($/) ; <FILE> };
211 my $patch_line = $_; 248 foreach my $line (keys %keyword_hash) {
212 foreach my $line (keys %keyword_hash) { 249 if ($text =~ m/$keyword_hash{$line}/x) {
213 if ($patch_line =~ m/^.*$keyword_hash{$line}/x) { 250 push(@keyword_tvi, $line);
214 push(@keyword_tvi, $line);
215 }
216 } 251 }
217 } 252 }
218 close(FILE); 253 close(FILE);
@@ -304,11 +339,11 @@ foreach my $file (@files) {
304 } 339 }
305 340
306 if ($email && $email_git) { 341 if ($email && $email_git) {
307 recent_git_signoffs($file); 342 vcs_file_signoffs($file);
308 } 343 }
309 344
310 if ($email && $email_git_blame) { 345 if ($email && $email_git_blame) {
311 git_assign_blame($file); 346 vcs_file_blame($file);
312 } 347 }
313} 348}
314 349
@@ -324,11 +359,11 @@ if ($email) {
324 if ($chief =~ m/^(.*):(.*)/) { 359 if ($chief =~ m/^(.*):(.*)/) {
325 my $email_address; 360 my $email_address;
326 361
327 $email_address = format_email($1, $2); 362 $email_address = format_email($1, $2, $email_usename);
328 if ($email_git_penguin_chiefs) { 363 if ($email_git_penguin_chiefs) {
329 push(@email_to, $email_address); 364 push(@email_to, [$email_address, 'chief penguin']);
330 } else { 365 } else {
331 @email_to = grep(!/${email_address}/, @email_to); 366 @email_to = grep($_->[0] !~ /${email_address}/, @email_to);
332 } 367 }
333 } 368 }
334 } 369 }
@@ -342,7 +377,7 @@ if ($email || $email_list) {
342 if ($email_list) { 377 if ($email_list) {
343 @to = (@to, @list_to); 378 @to = (@to, @list_to);
344 } 379 }
345 output(uniq(@to)); 380 output(merge_email(@to));
346} 381}
347 382
348if ($scm) { 383if ($scm) {
@@ -398,13 +433,16 @@ MAINTAINER field selection options:
398 --git-min-signatures => number of signatures required (default: 1) 433 --git-min-signatures => number of signatures required (default: 1)
399 --git-max-maintainers => maximum maintainers to add (default: 5) 434 --git-max-maintainers => maximum maintainers to add (default: 5)
400 --git-min-percent => minimum percentage of commits required (default: 5) 435 --git-min-percent => minimum percentage of commits required (default: 5)
401 --git-since => git history to use (default: 1-year-ago)
402 --git-blame => use git blame to find modified commits for patch or file 436 --git-blame => use git blame to find modified commits for patch or file
437 --git-since => git history to use (default: 1-year-ago)
438 --hg-since => hg history to use (default: -365)
403 --m => include maintainer(s) if any 439 --m => include maintainer(s) if any
404 --n => include name 'Full Name <addr\@domain.tld>' 440 --n => include name 'Full Name <addr\@domain.tld>'
405 --l => include list(s) if any 441 --l => include list(s) if any
406 --s => include subscriber only list(s) if any 442 --s => include subscriber only list(s) if any
407 --remove-duplicates => minimize duplicate email names/addresses 443 --remove-duplicates => minimize duplicate email names/addresses
444 --roles => show roles (status:subsystem, git-signer, list, etc...)
445 --rolestats => show roles and statistics (commits/total_commits, %)
408 --scm => print SCM tree(s) if any 446 --scm => print SCM tree(s) if any
409 --status => print status if any 447 --status => print status if any
410 --subsystem => print subsystem name if any 448 --subsystem => print subsystem name if any
@@ -430,11 +468,24 @@ Notes:
430 directory are examined as git recurses directories. 468 directory are examined as git recurses directories.
431 Any specified X: (exclude) pattern matches are _not_ ignored. 469 Any specified X: (exclude) pattern matches are _not_ ignored.
432 Used with "--nogit", directory is used as a pattern match, 470 Used with "--nogit", directory is used as a pattern match,
433 no individual file within the directory or subdirectory 471 no individual file within the directory or subdirectory
434 is matched. 472 is matched.
435 Used with "--git-blame", does not iterate all files in directory 473 Used with "--git-blame", does not iterate all files in directory
436 Using "--git-blame" is slow and may add old committers and authors 474 Using "--git-blame" is slow and may add old committers and authors
437 that are no longer active maintainers to the output. 475 that are no longer active maintainers to the output.
476 Using "--roles" or "--rolestats" with git send-email --cc-cmd or any
477 other automated tools that expect only ["name"] <email address>
478 may not work because of additional output after <email address>.
479 Using "--rolestats" and "--git-blame" shows the #/total=% commits,
480 not the percentage of the entire file authored. # of commits is
481 not a good measure of amount of code authored. 1 major commit may
482 contain a thousand lines, 5 trivial commits may modify a single line.
483 If git is not installed, but mercurial (hg) is installed and an .hg
484 repository exists, the following options apply to mercurial:
485 --git,
486 --git-min-signatures, --git-max-maintainers, --git-min-percent, and
487 --git-blame
488 Use --hg-since not --git-since to control date selection
438EOT 489EOT
439} 490}
440 491
@@ -493,7 +544,7 @@ sub parse_email {
493} 544}
494 545
495sub format_email { 546sub format_email {
496 my ($name, $address) = @_; 547 my ($name, $address, $usename) = @_;
497 548
498 my $formatted_email; 549 my $formatted_email;
499 550
@@ -506,11 +557,11 @@ sub format_email {
506 $name = "\"$name\""; 557 $name = "\"$name\"";
507 } 558 }
508 559
509 if ($email_usename) { 560 if ($usename) {
510 if ("$name" eq "") { 561 if ("$name" eq "") {
511 $formatted_email = "$address"; 562 $formatted_email = "$address";
512 } else { 563 } else {
513 $formatted_email = "$name <${address}>"; 564 $formatted_email = "$name <$address>";
514 } 565 }
515 } else { 566 } else {
516 $formatted_email = $address; 567 $formatted_email = $address;
@@ -547,6 +598,71 @@ sub find_ending_index {
547 return $index; 598 return $index;
548} 599}
549 600
601sub get_maintainer_role {
602 my ($index) = @_;
603
604 my $i;
605 my $start = find_starting_index($index);
606 my $end = find_ending_index($index);
607
608 my $role;
609 my $subsystem = $typevalue[$start];
610 if (length($subsystem) > 20) {
611 $subsystem = substr($subsystem, 0, 17);
612 $subsystem =~ s/\s*$//;
613 $subsystem = $subsystem . "...";
614 }
615
616 for ($i = $start + 1; $i < $end; $i++) {
617 my $tv = $typevalue[$i];
618 if ($tv =~ m/^(\C):\s*(.*)/) {
619 my $ptype = $1;
620 my $pvalue = $2;
621 if ($ptype eq "S") {
622 $role = $pvalue;
623 }
624 }
625 }
626
627 $role = lc($role);
628 if ($role eq "supported") {
629 $role = "supporter";
630 } elsif ($role eq "maintained") {
631 $role = "maintainer";
632 } elsif ($role eq "odd fixes") {
633 $role = "odd fixer";
634 } elsif ($role eq "orphan") {
635 $role = "orphan minder";
636 } elsif ($role eq "obsolete") {
637 $role = "obsolete minder";
638 } elsif ($role eq "buried alive in reporters") {
639 $role = "chief penguin";
640 }
641
642 return $role . ":" . $subsystem;
643}
644
645sub get_list_role {
646 my ($index) = @_;
647
648 my $i;
649 my $start = find_starting_index($index);
650 my $end = find_ending_index($index);
651
652 my $subsystem = $typevalue[$start];
653 if (length($subsystem) > 20) {
654 $subsystem = substr($subsystem, 0, 17);
655 $subsystem =~ s/\s*$//;
656 $subsystem = $subsystem . "...";
657 }
658
659 if ($subsystem eq "THE REST") {
660 $subsystem = "";
661 }
662
663 return $subsystem;
664}
665
550sub add_categories { 666sub add_categories {
551 my ($index) = @_; 667 my ($index) = @_;
552 668
@@ -564,17 +680,22 @@ sub add_categories {
564 if ($ptype eq "L") { 680 if ($ptype eq "L") {
565 my $list_address = $pvalue; 681 my $list_address = $pvalue;
566 my $list_additional = ""; 682 my $list_additional = "";
683 my $list_role = get_list_role($i);
684
685 if ($list_role ne "") {
686 $list_role = ":" . $list_role;
687 }
567 if ($list_address =~ m/([^\s]+)\s+(.*)$/) { 688 if ($list_address =~ m/([^\s]+)\s+(.*)$/) {
568 $list_address = $1; 689 $list_address = $1;
569 $list_additional = $2; 690 $list_additional = $2;
570 } 691 }
571 if ($list_additional =~ m/subscribers-only/) { 692 if ($list_additional =~ m/subscribers-only/) {
572 if ($email_subscriber_list) { 693 if ($email_subscriber_list) {
573 push(@list_to, $list_address); 694 push(@list_to, [$list_address, "subscriber list${list_role}"]);
574 } 695 }
575 } else { 696 } else {
576 if ($email_list) { 697 if ($email_list) {
577 push(@list_to, $list_address); 698 push(@list_to, [$list_address, "open list${list_role}"]);
578 } 699 }
579 } 700 }
580 } elsif ($ptype eq "M") { 701 } elsif ($ptype eq "M") {
@@ -585,13 +706,14 @@ sub add_categories {
585 if ($tv =~ m/^(\C):\s*(.*)/) { 706 if ($tv =~ m/^(\C):\s*(.*)/) {
586 if ($1 eq "P") { 707 if ($1 eq "P") {
587 $name = $2; 708 $name = $2;
588 $pvalue = format_email($name, $address); 709 $pvalue = format_email($name, $address, $email_usename);
589 } 710 }
590 } 711 }
591 } 712 }
592 } 713 }
593 if ($email_maintainer) { 714 if ($email_maintainer) {
594 push_email_addresses($pvalue); 715 my $role = get_maintainer_role($i);
716 push_email_addresses($pvalue, $role);
595 } 717 }
596 } elsif ($ptype eq "T") { 718 } elsif ($ptype eq "T") {
597 push(@scm, $pvalue); 719 push(@scm, $pvalue);
@@ -618,7 +740,7 @@ sub email_inuse {
618} 740}
619 741
620sub push_email_address { 742sub push_email_address {
621 my ($line) = @_; 743 my ($line, $role) = @_;
622 744
623 my ($name, $address) = parse_email($line); 745 my ($name, $address) = parse_email($line);
624 746
@@ -627,9 +749,9 @@ sub push_email_address {
627 } 749 }
628 750
629 if (!$email_remove_duplicates) { 751 if (!$email_remove_duplicates) {
630 push(@email_to, format_email($name, $address)); 752 push(@email_to, [format_email($name, $address, $email_usename), $role]);
631 } elsif (!email_inuse($name, $address)) { 753 } elsif (!email_inuse($name, $address)) {
632 push(@email_to, format_email($name, $address)); 754 push(@email_to, [format_email($name, $address, $email_usename), $role]);
633 $email_hash_name{$name}++; 755 $email_hash_name{$name}++;
634 $email_hash_address{$address}++; 756 $email_hash_address{$address}++;
635 } 757 }
@@ -638,24 +760,52 @@ sub push_email_address {
638} 760}
639 761
640sub push_email_addresses { 762sub push_email_addresses {
641 my ($address) = @_; 763 my ($address, $role) = @_;
642 764
643 my @address_list = (); 765 my @address_list = ();
644 766
645 if (rfc822_valid($address)) { 767 if (rfc822_valid($address)) {
646 push_email_address($address); 768 push_email_address($address, $role);
647 } elsif (@address_list = rfc822_validlist($address)) { 769 } elsif (@address_list = rfc822_validlist($address)) {
648 my $array_count = shift(@address_list); 770 my $array_count = shift(@address_list);
649 while (my $entry = shift(@address_list)) { 771 while (my $entry = shift(@address_list)) {
650 push_email_address($entry); 772 push_email_address($entry, $role);
651 } 773 }
652 } else { 774 } else {
653 if (!push_email_address($address)) { 775 if (!push_email_address($address, $role)) {
654 warn("Invalid MAINTAINERS address: '" . $address . "'\n"); 776 warn("Invalid MAINTAINERS address: '" . $address . "'\n");
655 } 777 }
656 } 778 }
657} 779}
658 780
781sub add_role {
782 my ($line, $role) = @_;
783
784 my ($name, $address) = parse_email($line);
785 my $email = format_email($name, $address, $email_usename);
786
787 foreach my $entry (@email_to) {
788 if ($email_remove_duplicates) {
789 my ($entry_name, $entry_address) = parse_email($entry->[0]);
790 if ($name eq $entry_name || $address eq $entry_address) {
791 if ($entry->[1] eq "") {
792 $entry->[1] = "$role";
793 } else {
794 $entry->[1] = "$entry->[1],$role";
795 }
796 }
797 } else {
798 if ($email eq $entry->[0]) {
799 if ($entry->[1] eq "") {
800 $entry->[1] = "$role";
801 } else {
802 $entry->[1] = "$entry->[1],$role";
803 }
804 }
805 }
806 }
807}
808
659sub which { 809sub which {
660 my ($bin) = @_; 810 my ($bin) = @_;
661 811
@@ -669,7 +819,7 @@ sub which {
669} 819}
670 820
671sub mailmap { 821sub mailmap {
672 my @lines = @_; 822 my (@lines) = @_;
673 my %hash; 823 my %hash;
674 824
675 foreach my $line (@lines) { 825 foreach my $line (@lines) {
@@ -678,14 +828,14 @@ sub mailmap {
678 $hash{$name} = $address; 828 $hash{$name} = $address;
679 } elsif ($address ne $hash{$name}) { 829 } elsif ($address ne $hash{$name}) {
680 $address = $hash{$name}; 830 $address = $hash{$name};
681 $line = format_email($name, $address); 831 $line = format_email($name, $address, $email_usename);
682 } 832 }
683 if (exists($mailmap{$name})) { 833 if (exists($mailmap{$name})) {
684 my $obj = $mailmap{$name}; 834 my $obj = $mailmap{$name};
685 foreach my $map_address (@$obj) { 835 foreach my $map_address (@$obj) {
686 if (($map_address eq $address) && 836 if (($map_address eq $address) &&
687 ($map_address ne $hash{$name})) { 837 ($map_address ne $hash{$name})) {
688 $line = format_email($name, $hash{$name}); 838 $line = format_email($name, $hash{$name}, $email_usename);
689 } 839 }
690 } 840 }
691 } 841 }
@@ -694,34 +844,38 @@ sub mailmap {
694 return @lines; 844 return @lines;
695} 845}
696 846
697sub recent_git_signoffs { 847sub git_execute_cmd {
698 my ($file) = @_; 848 my ($cmd) = @_;
699
700 my $sign_offs = "";
701 my $cmd = "";
702 my $output = "";
703 my $count = 0;
704 my @lines = (); 849 my @lines = ();
705 my %hash;
706 my $total_sign_offs;
707 850
708 if (which("git") eq "") { 851 my $output = `$cmd`;
709 warn("$P: git not found. Add --nogit to options?\n"); 852 $output =~ s/^\s*//gm;
710 return; 853 @lines = split("\n", $output);
711 }
712 if (!(-d ".git")) {
713 warn("$P: .git directory not found. Use a git repository for better results.\n");
714 warn("$P: perhaps 'git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git'\n");
715 return;
716 }
717 854
718 $cmd = "git log --since=${email_git_since} -- ${file}"; 855 return @lines;
856}
719 857
720 $output = `${cmd}`; 858sub hg_execute_cmd {
721 $output =~ s/^\s*//gm; 859 my ($cmd) = @_;
860 my @lines = ();
722 861
862 my $output = `$cmd`;
723 @lines = split("\n", $output); 863 @lines = split("\n", $output);
724 864
865 return @lines;
866}
867
868sub vcs_find_signers {
869 my ($cmd) = @_;
870 my @lines = ();
871 my $commits;
872
873 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
874
875 my $pattern = $VCS_cmds{"commit_pattern"};
876
877 $commits = grep(/$pattern/, @lines); # of commits
878
725 @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); 879 @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines);
726 if (!$email_git_penguin_chiefs) { 880 if (!$email_git_penguin_chiefs) {
727 @lines = grep(!/${penguin_chiefs}/i, @lines); 881 @lines = grep(!/${penguin_chiefs}/i, @lines);
@@ -729,111 +883,183 @@ sub recent_git_signoffs {
729 # cut -f2- -d":" 883 # cut -f2- -d":"
730 s/.*:\s*(.+)\s*/$1/ for (@lines); 884 s/.*:\s*(.+)\s*/$1/ for (@lines);
731 885
732 $total_sign_offs = @lines; 886## Reformat email addresses (with names) to avoid badly written signatures
733 887
734 if ($email_remove_duplicates) { 888 foreach my $line (@lines) {
735 @lines = mailmap(@lines); 889 my ($name, $address) = parse_email($line);
890 $line = format_email($name, $address, 1);
736 } 891 }
737 892
738 @lines = sort(@lines); 893 return ($commits, @lines);
739
740 # uniq -c
741 $hash{$_}++ for @lines;
742
743 # sort -rn
744 foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
745 my $sign_offs = $hash{$line};
746 $count++;
747 last if ($sign_offs < $email_git_min_signatures ||
748 $count > $email_git_max_maintainers ||
749 $sign_offs * 100 / $total_sign_offs < $email_git_min_percent);
750 push_email_address($line);
751 }
752} 894}
753 895
754sub save_commits { 896sub vcs_save_commits {
755 my ($cmd, @commits) = @_; 897 my ($cmd) = @_;
756 my $output;
757 my @lines = (); 898 my @lines = ();
899 my @commits = ();
758 900
759 $output = `${cmd}`; 901 @lines = &{$VCS_cmds{"execute_cmd"}}($cmd);
760 902
761 @lines = split("\n", $output);
762 foreach my $line (@lines) { 903 foreach my $line (@lines) {
763 if ($line =~ m/^(\w+) /) { 904 if ($line =~ m/$VCS_cmds{"blame_commit_pattern"}/) {
764 push (@commits, $1); 905 push(@commits, $1);
765 } 906 }
766 } 907 }
908
767 return @commits; 909 return @commits;
768} 910}
769 911
770sub git_assign_blame { 912sub vcs_blame {
771 my ($file) = @_; 913 my ($file) = @_;
772
773 my @lines = ();
774 my @commits = ();
775 my $cmd; 914 my $cmd;
776 my $output; 915 my @commits = ();
777 my %hash; 916
778 my $total_sign_offs; 917 return @commits if (!(-f $file));
779 my $count; 918
919 if (@range && $VCS_cmds{"blame_range_cmd"} eq "") {
920 my @all_commits = ();
921
922 $cmd = $VCS_cmds{"blame_file_cmd"};
923 $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
924 @all_commits = vcs_save_commits($cmd);
780 925
781 if (@range) {
782 foreach my $file_range_diff (@range) { 926 foreach my $file_range_diff (@range) {
783 next if (!($file_range_diff =~ m/(.+):(.+):(.+)/)); 927 next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
784 my $diff_file = $1; 928 my $diff_file = $1;
785 my $diff_start = $2; 929 my $diff_start = $2;
786 my $diff_length = $3; 930 my $diff_length = $3;
787 next if (!("$file" eq "$diff_file")); 931 next if ("$file" ne "$diff_file");
788 $cmd = "git blame -l -L $diff_start,+$diff_length $file"; 932 for (my $i = $diff_start; $i < $diff_start + $diff_length; $i++) {
789 @commits = save_commits($cmd, @commits); 933 push(@commits, $all_commits[$i]);
934 }
790 } 935 }
791 } else { 936 } elsif (@range) {
792 if (-f $file) { 937 foreach my $file_range_diff (@range) {
793 $cmd = "git blame -l $file"; 938 next if (!($file_range_diff =~ m/(.+):(.+):(.+)/));
794 @commits = save_commits($cmd, @commits); 939 my $diff_file = $1;
940 my $diff_start = $2;
941 my $diff_length = $3;
942 next if ("$file" ne "$diff_file");
943 $cmd = $VCS_cmds{"blame_range_cmd"};
944 $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
945 push(@commits, vcs_save_commits($cmd));
795 } 946 }
947 } else {
948 $cmd = $VCS_cmds{"blame_file_cmd"};
949 $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
950 @commits = vcs_save_commits($cmd);
796 } 951 }
797 952
798 $total_sign_offs = 0; 953 return @commits;
799 @commits = uniq(@commits); 954}
800 foreach my $commit (@commits) {
801 $cmd = "git log -1 ${commit}";
802 955
803 $output = `${cmd}`; 956my $printed_novcs = 0;
804 $output =~ s/^\s*//gm; 957sub vcs_exists {
805 @lines = split("\n", $output); 958 %VCS_cmds = %VCS_cmds_git;
959 return 1 if eval $VCS_cmds{"available"};
960 %VCS_cmds = %VCS_cmds_hg;
961 return 1 if eval $VCS_cmds{"available"};
962 %VCS_cmds = ();
963 if (!$printed_novcs) {
964 warn("$P: No supported VCS found. Add --nogit to options?\n");
965 warn("Using a git repository produces better results.\n");
966 warn("Try Linus Torvalds' latest git repository using:\n");
967 warn("git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git\n");
968 $printed_novcs = 1;
969 }
970 return 0;
971}
806 972
807 @lines = grep(/^[-_ a-z]+by:.*\@.*$/i, @lines); 973sub vcs_assign {
808 if (!$email_git_penguin_chiefs) { 974 my ($role, $divisor, @lines) = @_;
809 @lines = grep(!/${penguin_chiefs}/i, @lines);
810 }
811 975
812 # cut -f2- -d":" 976 my %hash;
813 s/.*:\s*(.+)\s*/$1/ for (@lines); 977 my $count = 0;
814 978
815 $total_sign_offs += @lines; 979 return if (@lines <= 0);
816 980
817 if ($email_remove_duplicates) { 981 if ($divisor <= 0) {
818 @lines = mailmap(@lines); 982 warn("Bad divisor in " . (caller(0))[3] . ": $divisor\n");
819 } 983 $divisor = 1;
984 }
820 985
821 $hash{$_}++ for @lines; 986 if ($email_remove_duplicates) {
987 @lines = mailmap(@lines);
822 } 988 }
823 989
824 $count = 0; 990 @lines = sort(@lines);
991
992 # uniq -c
993 $hash{$_}++ for @lines;
994
995 # sort -rn
825 foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) { 996 foreach my $line (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
826 my $sign_offs = $hash{$line}; 997 my $sign_offs = $hash{$line};
998 my $percent = $sign_offs * 100 / $divisor;
999
1000 $percent = 100 if ($percent > 100);
827 $count++; 1001 $count++;
828 last if ($sign_offs < $email_git_min_signatures || 1002 last if ($sign_offs < $email_git_min_signatures ||
829 $count > $email_git_max_maintainers || 1003 $count > $email_git_max_maintainers ||
830 $sign_offs * 100 / $total_sign_offs < $email_git_min_percent); 1004 $percent < $email_git_min_percent);
831 push_email_address($line); 1005 push_email_address($line, '');
1006 if ($output_rolestats) {
1007 my $fmt_percent = sprintf("%.0f", $percent);
1008 add_role($line, "$role:$sign_offs/$divisor=$fmt_percent%");
1009 } else {
1010 add_role($line, $role);
1011 }
1012 }
1013}
1014
1015sub vcs_file_signoffs {
1016 my ($file) = @_;
1017
1018 my @signers = ();
1019 my $commits;
1020
1021 return if (!vcs_exists());
1022
1023 my $cmd = $VCS_cmds{"find_signers_cmd"};
1024 $cmd =~ s/(\$\w+)/$1/eeg; # interpolate $cmd
1025
1026 ($commits, @signers) = vcs_find_signers($cmd);
1027 vcs_assign("commit_signer", $commits, @signers);
1028}
1029
1030sub vcs_file_blame {
1031 my ($file) = @_;
1032
1033 my @signers = ();
1034 my @commits = ();
1035 my $total_commits;
1036
1037 return if (!vcs_exists());
1038
1039 @commits = vcs_blame($file);
1040 @commits = uniq(@commits);
1041 $total_commits = @commits;
1042
1043 foreach my $commit (@commits) {
1044 my $commit_count;
1045 my @commit_signers = ();
1046
1047 my $cmd = $VCS_cmds{"find_commit_signers_cmd"};
1048 $cmd =~ s/(\$\w+)/$1/eeg; #interpolate $cmd
1049
1050 ($commit_count, @commit_signers) = vcs_find_signers($cmd);
1051 push(@signers, @commit_signers);
1052 }
1053
1054 if ($from_filename) {
1055 vcs_assign("commits", $total_commits, @signers);
1056 } else {
1057 vcs_assign("modified commits", $total_commits, @signers);
832 } 1058 }
833} 1059}
834 1060
835sub uniq { 1061sub uniq {
836 my @parms = @_; 1062 my (@parms) = @_;
837 1063
838 my %saw; 1064 my %saw;
839 @parms = grep(!$saw{$_}++, @parms); 1065 @parms = grep(!$saw{$_}++, @parms);
@@ -841,7 +1067,7 @@ sub uniq {
841} 1067}
842 1068
843sub sort_and_uniq { 1069sub sort_and_uniq {
844 my @parms = @_; 1070 my (@parms) = @_;
845 1071
846 my %saw; 1072 my %saw;
847 @parms = sort @parms; 1073 @parms = sort @parms;
@@ -849,8 +1075,27 @@ sub sort_and_uniq {
849 return @parms; 1075 return @parms;
850} 1076}
851 1077
1078sub merge_email {
1079 my @lines;
1080 my %saw;
1081
1082 for (@_) {
1083 my ($address, $role) = @$_;
1084 if (!$saw{$address}) {
1085 if ($output_roles) {
1086 push(@lines, "$address ($role)");
1087 } else {
1088 push(@lines, $address);
1089 }
1090 $saw{$address} = 1;
1091 }
1092 }
1093
1094 return @lines;
1095}
1096
852sub output { 1097sub output {
853 my @parms = @_; 1098 my (@parms) = @_;
854 1099
855 if ($output_multiline) { 1100 if ($output_multiline) {
856 foreach my $line (@parms) { 1101 foreach my $line (@parms) {
@@ -947,11 +1192,9 @@ sub rfc822_validlist ($) {
947 if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so && 1192 if ($s =~ m/^(?:$rfc822re)?(?:,(?:$rfc822re)?)*$/so &&
948 $s =~ m/^$rfc822_char*$/) { 1193 $s =~ m/^$rfc822_char*$/) {
949 while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) { 1194 while ($s =~ m/(?:^|,$rfc822_lwsp*)($rfc822re)/gos) {
950 push @r, $1; 1195 push(@r, $1);
951 } 1196 }
952 return wantarray ? (scalar(@r), @r) : 1; 1197 return wantarray ? (scalar(@r), @r) : 1;
953 } 1198 }
954 else { 1199 return wantarray ? () : 0;
955 return wantarray ? () : 0;
956 }
957} 1200}
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c
index d82953573588..8413cf38ed27 100644
--- a/scripts/kconfig/mconf.c
+++ b/scripts/kconfig/mconf.c
@@ -213,7 +213,7 @@ load_config_help[] = N_(
213 "to modify that configuration.\n" 213 "to modify that configuration.\n"
214 "\n" 214 "\n"
215 "If you are uncertain, then you have probably never used alternate\n" 215 "If you are uncertain, then you have probably never used alternate\n"
216 "configuration files. You should therefor leave this blank to abort.\n"), 216 "configuration files. You should therefore leave this blank to abort.\n"),
217save_config_text[] = N_( 217save_config_text[] = N_(
218 "Enter a filename to which this configuration should be saved " 218 "Enter a filename to which this configuration should be saved "
219 "as an alternate. Leave blank to abort."), 219 "as an alternate. Leave blank to abort."),
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index ea9f8a58678f..241310e59cd6 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -1852,10 +1852,17 @@ sub tracepoint_munge($) {
1852 my $tracepointname = 0; 1852 my $tracepointname = 0;
1853 my $tracepointargs = 0; 1853 my $tracepointargs = 0;
1854 1854
1855 if($prototype =~ m/TRACE_EVENT\((.*?),/) { 1855 if ($prototype =~ m/TRACE_EVENT\((.*?),/) {
1856 $tracepointname = $1; 1856 $tracepointname = $1;
1857 } 1857 }
1858 if($prototype =~ m/TP_PROTO\((.*?)\)/) { 1858 if ($prototype =~ m/DEFINE_SINGLE_EVENT\((.*?),/) {
1859 $tracepointname = $1;
1860 }
1861 if ($prototype =~ m/DEFINE_EVENT\((.*?),(.*?),/) {
1862 $tracepointname = $2;
1863 }
1864 $tracepointname =~ s/^\s+//; #strip leading whitespace
1865 if ($prototype =~ m/TP_PROTO\((.*?)\)/) {
1859 $tracepointargs = $1; 1866 $tracepointargs = $1;
1860 } 1867 }
1861 if (($tracepointname eq 0) || ($tracepointargs eq 0)) { 1868 if (($tracepointname eq 0) || ($tracepointargs eq 0)) {
@@ -1920,7 +1927,9 @@ sub process_state3_function($$) {
1920 if ($prototype =~ /SYSCALL_DEFINE/) { 1927 if ($prototype =~ /SYSCALL_DEFINE/) {
1921 syscall_munge(); 1928 syscall_munge();
1922 } 1929 }
1923 if ($prototype =~ /TRACE_EVENT/) { 1930 if ($prototype =~ /TRACE_EVENT/ || $prototype =~ /DEFINE_EVENT/ ||
1931 $prototype =~ /DEFINE_SINGLE_EVENT/)
1932 {
1924 tracepoint_munge($file); 1933 tracepoint_munge($file);
1925 } 1934 }
1926 dump_function($prototype, $file); 1935 dump_function($prototype, $file);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 62a9025cdcc7..6f426afbc522 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -104,7 +104,7 @@ static void device_id_check(const char *modname, const char *device_id,
104static void do_usb_entry(struct usb_device_id *id, 104static void do_usb_entry(struct usb_device_id *id,
105 unsigned int bcdDevice_initial, int bcdDevice_initial_digits, 105 unsigned int bcdDevice_initial, int bcdDevice_initial_digits,
106 unsigned char range_lo, unsigned char range_hi, 106 unsigned char range_lo, unsigned char range_hi,
107 struct module *mod) 107 unsigned char max, struct module *mod)
108{ 108{
109 char alias[500]; 109 char alias[500];
110 strcpy(alias, "usb:"); 110 strcpy(alias, "usb:");
@@ -118,9 +118,22 @@ static void do_usb_entry(struct usb_device_id *id,
118 sprintf(alias + strlen(alias), "%0*X", 118 sprintf(alias + strlen(alias), "%0*X",
119 bcdDevice_initial_digits, bcdDevice_initial); 119 bcdDevice_initial_digits, bcdDevice_initial);
120 if (range_lo == range_hi) 120 if (range_lo == range_hi)
121 sprintf(alias + strlen(alias), "%u", range_lo); 121 sprintf(alias + strlen(alias), "%X", range_lo);
122 else if (range_lo > 0 || range_hi < 9) 122 else if (range_lo > 0 || range_hi < max) {
123 sprintf(alias + strlen(alias), "[%u-%u]", range_lo, range_hi); 123 if (range_lo > 0x9 || range_hi < 0xA)
124 sprintf(alias + strlen(alias),
125 "[%X-%X]",
126 range_lo,
127 range_hi);
128 else {
129 sprintf(alias + strlen(alias),
130 range_lo < 0x9 ? "[%X-9" : "[%X",
131 range_lo);
132 sprintf(alias + strlen(alias),
133 range_hi > 0xA ? "a-%X]" : "%X]",
134 range_lo);
135 }
136 }
124 if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1)) 137 if (bcdDevice_initial_digits < (sizeof(id->bcdDevice_lo) * 2 - 1))
125 strcat(alias, "*"); 138 strcat(alias, "*");
126 139
@@ -147,10 +160,49 @@ static void do_usb_entry(struct usb_device_id *id,
147 "MODULE_ALIAS(\"%s\");\n", alias); 160 "MODULE_ALIAS(\"%s\");\n", alias);
148} 161}
149 162
163/* Handles increment/decrement of BCD formatted integers */
164/* Returns the previous value, so it works like i++ or i-- */
165static unsigned int incbcd(unsigned int *bcd,
166 int inc,
167 unsigned char max,
168 size_t chars)
169{
170 unsigned int init = *bcd, i, j;
171 unsigned long long c, dec = 0;
172
173 /* If bcd is not in BCD format, just increment */
174 if (max > 0x9) {
175 *bcd += inc;
176 return init;
177 }
178
179 /* Convert BCD to Decimal */
180 for (i=0 ; i < chars ; i++) {
181 c = (*bcd >> (i << 2)) & 0xf;
182 c = c > 9 ? 9 : c; /* force to bcd just in case */
183 for (j=0 ; j < i ; j++)
184 c = c * 10;
185 dec += c;
186 }
187
188 /* Do our increment/decrement */
189 dec += inc;
190 *bcd = 0;
191
192 /* Convert back to BCD */
193 for (i=0 ; i < chars ; i++) {
194 for (c=1,j=0 ; j < i ; j++)
195 c = c * 10;
196 c = (dec / c) % 10;
197 *bcd += c << (i << 2);
198 }
199 return init;
200}
201
150static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod) 202static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
151{ 203{
152 unsigned int devlo, devhi; 204 unsigned int devlo, devhi;
153 unsigned char chi, clo; 205 unsigned char chi, clo, max;
154 int ndigits; 206 int ndigits;
155 207
156 id->match_flags = TO_NATIVE(id->match_flags); 208 id->match_flags = TO_NATIVE(id->match_flags);
@@ -162,6 +214,17 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
162 devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ? 214 devhi = id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI ?
163 TO_NATIVE(id->bcdDevice_hi) : ~0x0U; 215 TO_NATIVE(id->bcdDevice_hi) : ~0x0U;
164 216
217 /* Figure out if this entry is in bcd or hex format */
218 max = 0x9; /* Default to decimal format */
219 for (ndigits = 0 ; ndigits < sizeof(id->bcdDevice_lo) * 2 ; ndigits++) {
220 clo = (devlo >> (ndigits << 2)) & 0xf;
221 chi = ((devhi > 0x9999 ? 0x9999 : devhi) >> (ndigits << 2)) & 0xf;
222 if (clo > max || chi > max) {
223 max = 0xf;
224 break;
225 }
226 }
227
165 /* 228 /*
166 * Some modules (visor) have empty slots as placeholder for 229 * Some modules (visor) have empty slots as placeholder for
167 * run-time specification that results in catch-all alias 230 * run-time specification that results in catch-all alias
@@ -173,21 +236,27 @@ static void do_usb_entry_multi(struct usb_device_id *id, struct module *mod)
173 for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) { 236 for (ndigits = sizeof(id->bcdDevice_lo) * 2 - 1; devlo <= devhi; ndigits--) {
174 clo = devlo & 0xf; 237 clo = devlo & 0xf;
175 chi = devhi & 0xf; 238 chi = devhi & 0xf;
176 if (chi > 9) /* it's bcd not hex */ 239 if (chi > max) /* If we are in bcd mode, truncate if necessary */
177 chi = 9; 240 chi = max;
178 devlo >>= 4; 241 devlo >>= 4;
179 devhi >>= 4; 242 devhi >>= 4;
180 243
181 if (devlo == devhi || !ndigits) { 244 if (devlo == devhi || !ndigits) {
182 do_usb_entry(id, devlo, ndigits, clo, chi, mod); 245 do_usb_entry(id, devlo, ndigits, clo, chi, max, mod);
183 break; 246 break;
184 } 247 }
185 248
186 if (clo > 0) 249 if (clo > 0x0)
187 do_usb_entry(id, devlo++, ndigits, clo, 9, mod); 250 do_usb_entry(id,
188 251 incbcd(&devlo, 1, max,
189 if (chi < 9) 252 sizeof(id->bcdDevice_lo) * 2),
190 do_usb_entry(id, devhi--, ndigits, 0, chi, mod); 253 ndigits, clo, max, max, mod);
254
255 if (chi < max)
256 do_usb_entry(id,
257 incbcd(&devhi, -1, max,
258 sizeof(id->bcdDevice_lo) * 2),
259 ndigits, 0x0, chi, max, mod);
191 } 260 }
192} 261}
193 262
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
index 090d300d7394..9cf0a6fad6ba 100755
--- a/scripts/recordmcount.pl
+++ b/scripts/recordmcount.pl
@@ -6,77 +6,93 @@
6# all the offsets to the calls to mcount. 6# all the offsets to the calls to mcount.
7# 7#
8# 8#
9# What we want to end up with is a section in vmlinux called 9# What we want to end up with this is that each object file will have a
10# __mcount_loc that contains a list of pointers to all the 10# section called __mcount_loc that will hold the list of pointers to mcount
11# call sites in the kernel that call mcount. Later on boot up, the kernel 11# callers. After final linking, the vmlinux will have within .init.data the
12# will read this list, save the locations and turn them into nops. 12# list of all callers to mcount between __start_mcount_loc and __stop_mcount_loc.
13# When tracing or profiling is later enabled, these locations will then 13# Later on boot up, the kernel will read this list, save the locations and turn
14# be converted back to pointers to some function. 14# them into nops. When tracing or profiling is later enabled, these locations
15# will then be converted back to pointers to some function.
15# 16#
16# This is no easy feat. This script is called just after the original 17# This is no easy feat. This script is called just after the original
17# object is compiled and before it is linked. 18# object is compiled and before it is linked.
18# 19#
19# The references to the call sites are offsets from the section of text 20# When parse this object file using 'objdump', the references to the call
20# that the call site is in. Hence, all functions in a section that 21# sites are offsets from the section that the call site is in. Hence, all
21# has a call site to mcount, will have the offset from the beginning of 22# functions in a section that has a call site to mcount, will have the
22# the section and not the beginning of the function. 23# offset from the beginning of the section and not the beginning of the
24# function.
25#
26# But where this section will reside finally in vmlinx is undetermined at
27# this point. So we can't use this kind of offsets to record the final
28# address of this call site.
29#
30# The trick is to change the call offset referring the start of a section to
31# referring a function symbol in this section. During the link step, 'ld' will
32# compute the final address according to the information we record.
23# 33#
24# The trick is to find a way to record the beginning of the section.
25# The way we do this is to look at the first function in the section
26# which will also be the location of that section after final link.
27# e.g. 34# e.g.
28# 35#
29# .section ".sched.text", "ax" 36# .section ".sched.text", "ax"
30# .globl my_func
31# my_func:
32# [...] 37# [...]
33# call mcount (offset: 0x5) 38# func1:
39# [...]
40# call mcount (offset: 0x10)
34# [...] 41# [...]
35# ret 42# ret
36# other_func: 43# .globl fun2
44# func2: (offset: 0x20)
37# [...] 45# [...]
38# call mcount (offset: 0x1b) 46# [...]
47# ret
48# func3:
49# [...]
50# call mcount (offset: 0x30)
39# [...] 51# [...]
40# 52#
41# Both relocation offsets for the mcounts in the above example will be 53# Both relocation offsets for the mcounts in the above example will be
42# offset from .sched.text. If we make another file called tmp.s with: 54# offset from .sched.text. If we choose global symbol func2 as a reference and
55# make another file called tmp.s with the new offsets:
43# 56#
44# .section __mcount_loc 57# .section __mcount_loc
45# .quad my_func + 0x5 58# .quad func2 - 0x10
46# .quad my_func + 0x1b 59# .quad func2 + 0x10
47# 60#
48# We can then compile this tmp.s into tmp.o, and link it to the original 61# We can then compile this tmp.s into tmp.o, and link it back to the original
49# object. 62# object.
50# 63#
51# But this gets hard if my_func is not globl (a static function). 64# In our algorithm, we will choose the first global function we meet in this
52# In such a case we have: 65# section as the reference. But this gets hard if there is no global functions
66# in this section. In such a case we have to select a local one. E.g. func1:
53# 67#
54# .section ".sched.text", "ax" 68# .section ".sched.text", "ax"
55# my_func: 69# func1:
56# [...] 70# [...]
57# call mcount (offset: 0x5) 71# call mcount (offset: 0x10)
58# [...] 72# [...]
59# ret 73# ret
60# other_func: 74# func2:
61# [...] 75# [...]
62# call mcount (offset: 0x1b) 76# call mcount (offset: 0x20)
63# [...] 77# [...]
78# .section "other.section"
64# 79#
65# If we make the tmp.s the same as above, when we link together with 80# If we make the tmp.s the same as above, when we link together with
66# the original object, we will end up with two symbols for my_func: 81# the original object, we will end up with two symbols for func1:
67# one local, one global. After final compile, we will end up with 82# one local, one global. After final compile, we will end up with
68# an undefined reference to my_func. 83# an undefined reference to func1 or a wrong reference to another global
84# func1 in other files.
69# 85#
70# Since local objects can reference local variables, we need to find 86# Since local objects can reference local variables, we need to find
71# a way to make tmp.o reference the local objects of the original object 87# a way to make tmp.o reference the local objects of the original object
72# file after it is linked together. To do this, we convert the my_func 88# file after it is linked together. To do this, we convert func1
73# into a global symbol before linking tmp.o. Then after we link tmp.o 89# into a global symbol before linking tmp.o. Then after we link tmp.o
74# we will only have a single symbol for my_func that is global. 90# we will only have a single symbol for func1 that is global.
75# We can convert my_func back into a local symbol and we are done. 91# We can convert func1 back into a local symbol and we are done.
76# 92#
77# Here are the steps we take: 93# Here are the steps we take:
78# 94#
79# 1) Record all the local symbols by using 'nm' 95# 1) Record all the local and weak symbols by using 'nm'
80# 2) Use objdump to find all the call site offsets and sections for 96# 2) Use objdump to find all the call site offsets and sections for
81# mcount. 97# mcount.
82# 3) Compile the list into its own object. 98# 3) Compile the list into its own object.
@@ -86,10 +102,8 @@
86# 6) Link together this new object with the list object. 102# 6) Link together this new object with the list object.
87# 7) Convert the local functions back to local symbols and rename 103# 7) Convert the local functions back to local symbols and rename
88# the result as the original object. 104# the result as the original object.
89# End.
90# 8) Link the object with the list object. 105# 8) Link the object with the list object.
91# 9) Move the result back to the original object. 106# 9) Move the result back to the original object.
92# End.
93# 107#
94 108
95use strict; 109use strict;
@@ -99,7 +113,7 @@ $P =~ s@.*/@@g;
99 113
100my $V = '0.1'; 114my $V = '0.1';
101 115
102if ($#ARGV < 7) { 116if ($#ARGV != 10) {
103 print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n"; 117 print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
104 print "version: $V\n"; 118 print "version: $V\n";
105 exit(1); 119 exit(1);
@@ -109,7 +123,7 @@ my ($arch, $bits, $objdump, $objcopy, $cc,
109 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV; 123 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
110 124
111# This file refers to mcount and shouldn't be ftraced, so lets' ignore it 125# This file refers to mcount and shouldn't be ftraced, so lets' ignore it
112if ($inputfile eq "kernel/trace/ftrace.o") { 126if ($inputfile =~ m,kernel/trace/ftrace\.o$,) {
113 exit(0); 127 exit(0);
114} 128}
115 129
@@ -119,6 +133,7 @@ my %text_sections = (
119 ".sched.text" => 1, 133 ".sched.text" => 1,
120 ".spinlock.text" => 1, 134 ".spinlock.text" => 1,
121 ".irqentry.text" => 1, 135 ".irqentry.text" => 1,
136 ".text.unlikely" => 1,
122); 137);
123 138
124$objdump = "objdump" if ((length $objdump) == 0); 139$objdump = "objdump" if ((length $objdump) == 0);
@@ -137,13 +152,47 @@ my %weak; # List of weak functions
137my %convert; # List of local functions used that needs conversion 152my %convert; # List of local functions used that needs conversion
138 153
139my $type; 154my $type;
140my $nm_regex; # Find the local functions (return function) 155my $local_regex; # Match a local function (return function)
156my $weak_regex; # Match a weak function (return function)
141my $section_regex; # Find the start of a section 157my $section_regex; # Find the start of a section
142my $function_regex; # Find the name of a function 158my $function_regex; # Find the name of a function
143 # (return offset and func name) 159 # (return offset and func name)
144my $mcount_regex; # Find the call site to mcount (return offset) 160my $mcount_regex; # Find the call site to mcount (return offset)
145my $alignment; # The .align value to use for $mcount_section 161my $alignment; # The .align value to use for $mcount_section
146my $section_type; # Section header plus possible alignment command 162my $section_type; # Section header plus possible alignment command
163my $can_use_local = 0; # If we can use local function references
164
165# Shut up recordmcount if user has older objcopy
166my $quiet_recordmcount = ".tmp_quiet_recordmcount";
167my $print_warning = 1;
168$print_warning = 0 if ( -f $quiet_recordmcount);
169
170##
171# check_objcopy - whether objcopy supports --globalize-symbols
172#
173# --globalize-symbols came out in 2.17, we must test the version
174# of objcopy, and if it is less than 2.17, then we can not
175# record local functions.
176sub check_objcopy
177{
178 open (IN, "$objcopy --version |") or die "error running $objcopy";
179 while (<IN>) {
180 if (/objcopy.*\s(\d+)\.(\d+)/) {
181 $can_use_local = 1 if ($1 > 2 || ($1 == 2 && $2 >= 17));
182 last;
183 }
184 }
185 close (IN);
186
187 if (!$can_use_local && $print_warning) {
188 print STDERR "WARNING: could not find objcopy version or version " .
189 "is less than 2.17.\n" .
190 "\tLocal function references are disabled.\n";
191 open (QUIET, ">$quiet_recordmcount");
192 printf QUIET "Disables the warning from recordmcount.pl\n";
193 close QUIET;
194 }
195}
147 196
148if ($arch eq "x86") { 197if ($arch eq "x86") {
149 if ($bits == 64) { 198 if ($bits == 64) {
@@ -157,7 +206,8 @@ if ($arch eq "x86") {
157# We base the defaults off of i386, the other archs may 206# We base the defaults off of i386, the other archs may
158# feel free to change them in the below if statements. 207# feel free to change them in the below if statements.
159# 208#
160$nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)"; 209$local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)";
210$weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)";
161$section_regex = "Disassembly of section\\s+(\\S+):"; 211$section_regex = "Disassembly of section\\s+(\\S+):";
162$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:"; 212$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
163$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$"; 213$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
@@ -206,7 +256,7 @@ if ($arch eq "x86_64") {
206 $cc .= " -m32"; 256 $cc .= " -m32";
207 257
208} elsif ($arch eq "powerpc") { 258} elsif ($arch eq "powerpc") {
209 $nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; 259 $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";
210 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:"; 260 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";
211 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; 261 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";
212 262
@@ -245,6 +295,9 @@ if ($arch eq "x86_64") {
245 $ld .= " -m elf64_sparc"; 295 $ld .= " -m elf64_sparc";
246 $cc .= " -m64"; 296 $cc .= " -m64";
247 $objcopy .= " -O elf64-sparc"; 297 $objcopy .= " -O elf64-sparc";
298} elsif ($arch eq "microblaze") {
299 # Microblaze calls '_mcount' instead of plain 'mcount'.
300 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s_mcount\$";
248} else { 301} else {
249 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD"; 302 die "Arch $arch is not supported with CONFIG_FTRACE_MCOUNT_RECORD";
250} 303}
@@ -278,44 +331,17 @@ if ($filename =~ m,^(.*)(\.\S),) {
278my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s"; 331my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";
279my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o"; 332my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";
280 333
281# 334check_objcopy();
282# --globalize-symbols came out in 2.17, we must test the version
283# of objcopy, and if it is less than 2.17, then we can not
284# record local functions.
285my $use_locals = 01;
286my $local_warn_once = 0;
287my $found_version = 0;
288
289open (IN, "$objcopy --version |") || die "error running $objcopy";
290while (<IN>) {
291 if (/objcopy.*\s(\d+)\.(\d+)/) {
292 my $major = $1;
293 my $minor = $2;
294
295 $found_version = 1;
296 if ($major < 2 ||
297 ($major == 2 && $minor < 17)) {
298 $use_locals = 0;
299 }
300 last;
301 }
302}
303close (IN);
304
305if (!$found_version) {
306 print STDERR "WARNING: could not find objcopy version.\n" .
307 "\tDisabling local function references.\n";
308}
309 335
310# 336#
311# Step 1: find all the local (static functions) and weak symbols. 337# Step 1: find all the local (static functions) and weak symbols.
312# 't' is local, 'w/W' is weak (we never use a weak function) 338# 't' is local, 'w/W' is weak
313# 339#
314open (IN, "$nm $inputfile|") || die "error running $nm"; 340open (IN, "$nm $inputfile|") || die "error running $nm";
315while (<IN>) { 341while (<IN>) {
316 if (/$nm_regex/) { 342 if (/$local_regex/) {
317 $locals{$1} = 1; 343 $locals{$1} = 1;
318 } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) { 344 } elsif (/$weak_regex/) {
319 $weak{$2} = $1; 345 $weak{$2} = $1;
320 } 346 }
321} 347}
@@ -333,26 +359,20 @@ my $offset = 0; # offset of ref_func to section beginning
333# 359#
334sub update_funcs 360sub update_funcs
335{ 361{
336 return if ($#offsets < 0); 362 return unless ($ref_func and @offsets);
337 363
338 defined($ref_func) || die "No function to reference"; 364 # Sanity check on weak function. A weak function may be overwritten by
339 365 # another function of the same name, making all these offsets incorrect.
340 # A section only had a weak function, to represent it.
341 # Unfortunately, a weak function may be overwritten by another
342 # function of the same name, making all these offsets incorrect.
343 # To be safe, we simply print a warning and bail.
344 if (defined $weak{$ref_func}) { 366 if (defined $weak{$ref_func}) {
345 print STDERR 367 die "$inputfile: ERROR: referencing weak function" .
346 "$inputfile: WARNING: referencing weak function" .
347 " $ref_func for mcount\n"; 368 " $ref_func for mcount\n";
348 return;
349 } 369 }
350 370
351 # is this function static? If so, note this fact. 371 # is this function static? If so, note this fact.
352 if (defined $locals{$ref_func}) { 372 if (defined $locals{$ref_func}) {
353 373
354 # only use locals if objcopy supports globalize-symbols 374 # only use locals if objcopy supports globalize-symbols
355 if (!$use_locals) { 375 if (!$can_use_local) {
356 return; 376 return;
357 } 377 }
358 $convert{$ref_func} = 1; 378 $convert{$ref_func} = 1;
@@ -378,9 +398,27 @@ open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump";
378 398
379my $text; 399my $text;
380 400
401
402# read headers first
381my $read_headers = 1; 403my $read_headers = 1;
382 404
383while (<IN>) { 405while (<IN>) {
406
407 if ($read_headers && /$mcount_section/) {
408 #
409 # Somehow the make process can execute this script on an
410 # object twice. If it does, we would duplicate the mcount
411 # section and it will cause the function tracer self test
412 # to fail. Check if the mcount section exists, and if it does,
413 # warn and exit.
414 #
415 print STDERR "ERROR: $mcount_section already in $inputfile\n" .
416 "\tThis may be an indication that your build is corrupted.\n" .
417 "\tDelete $inputfile and try again. If the same object file\n" .
418 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
419 exit(-1);
420 }
421
384 # is it a section? 422 # is it a section?
385 if (/$section_regex/) { 423 if (/$section_regex/) {
386 $read_headers = 0; 424 $read_headers = 0;
@@ -392,7 +430,7 @@ while (<IN>) {
392 $read_function = 0; 430 $read_function = 0;
393 } 431 }
394 # print out any recorded offsets 432 # print out any recorded offsets
395 update_funcs() if (defined($ref_func)); 433 update_funcs();
396 434
397 # reset all markers and arrays 435 # reset all markers and arrays
398 $text_found = 0; 436 $text_found = 0;
@@ -421,21 +459,7 @@ while (<IN>) {
421 $offset = hex $1; 459 $offset = hex $1;
422 } 460 }
423 } 461 }
424 } elsif ($read_headers && /$mcount_section/) {
425 #
426 # Somehow the make process can execute this script on an
427 # object twice. If it does, we would duplicate the mcount
428 # section and it will cause the function tracer self test
429 # to fail. Check if the mcount section exists, and if it does,
430 # warn and exit.
431 #
432 print STDERR "ERROR: $mcount_section already in $inputfile\n" .
433 "\tThis may be an indication that your build is corrupted.\n" .
434 "\tDelete $inputfile and try again. If the same object file\n" .
435 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
436 exit(-1);
437 } 462 }
438
439 # is this a call site to mcount? If so, record it to print later 463 # is this a call site to mcount? If so, record it to print later
440 if ($text_found && /$mcount_regex/) { 464 if ($text_found && /$mcount_regex/) {
441 $offsets[$#offsets + 1] = hex $1; 465 $offsets[$#offsets + 1] = hex $1;
@@ -443,7 +467,7 @@ while (<IN>) {
443} 467}
444 468
445# dump out anymore offsets that may have been found 469# dump out anymore offsets that may have been found
446update_funcs() if (defined($ref_func)); 470update_funcs();
447 471
448# If we did not find any mcount callers, we are done (do nothing). 472# If we did not find any mcount callers, we are done (do nothing).
449if (!$opened) { 473if (!$opened) {
diff --git a/scripts/selinux/Makefile b/scripts/selinux/Makefile
index ca4b1ec01822..e8049da1831f 100644
--- a/scripts/selinux/Makefile
+++ b/scripts/selinux/Makefile
@@ -1,2 +1,2 @@
1subdir-y := mdp 1subdir-y := mdp genheaders
2subdir- += mdp 2subdir- += mdp genheaders
diff --git a/scripts/selinux/genheaders/.gitignore b/scripts/selinux/genheaders/.gitignore
new file mode 100644
index 000000000000..4c0b646ff8d5
--- /dev/null
+++ b/scripts/selinux/genheaders/.gitignore
@@ -0,0 +1 @@
genheaders
diff --git a/scripts/selinux/genheaders/Makefile b/scripts/selinux/genheaders/Makefile
new file mode 100644
index 000000000000..417b165008ee
--- /dev/null
+++ b/scripts/selinux/genheaders/Makefile
@@ -0,0 +1,5 @@
1hostprogs-y := genheaders
2HOST_EXTRACFLAGS += -Isecurity/selinux/include
3
4always := $(hostprogs-y)
5clean-files := $(hostprogs-y)
diff --git a/scripts/selinux/genheaders/genheaders.c b/scripts/selinux/genheaders/genheaders.c
new file mode 100644
index 000000000000..24626968055d
--- /dev/null
+++ b/scripts/selinux/genheaders/genheaders.c
@@ -0,0 +1,118 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <string.h>
5#include <errno.h>
6#include <ctype.h>
7
8struct security_class_mapping {
9 const char *name;
10 const char *perms[sizeof(unsigned) * 8 + 1];
11};
12
13#include "classmap.h"
14#include "initial_sid_to_string.h"
15
16#define max(x, y) (((int)(x) > (int)(y)) ? x : y)
17
18const char *progname;
19
20static void usage(void)
21{
22 printf("usage: %s flask.h av_permissions.h\n", progname);
23 exit(1);
24}
25
26static char *stoupperx(const char *s)
27{
28 char *s2 = strdup(s);
29 char *p;
30
31 if (!s2) {
32 fprintf(stderr, "%s: out of memory\n", progname);
33 exit(3);
34 }
35
36 for (p = s2; *p; p++)
37 *p = toupper(*p);
38 return s2;
39}
40
41int main(int argc, char *argv[])
42{
43 int i, j, k;
44 int isids_len;
45 FILE *fout;
46
47 progname = argv[0];
48
49 if (argc < 3)
50 usage();
51
52 fout = fopen(argv[1], "w");
53 if (!fout) {
54 fprintf(stderr, "Could not open %s for writing: %s\n",
55 argv[1], strerror(errno));
56 exit(2);
57 }
58
59 for (i = 0; secclass_map[i].name; i++) {
60 struct security_class_mapping *map = &secclass_map[i];
61 map->name = stoupperx(map->name);
62 for (j = 0; map->perms[j]; j++)
63 map->perms[j] = stoupperx(map->perms[j]);
64 }
65
66 isids_len = sizeof(initial_sid_to_string) / sizeof (char *);
67 for (i = 1; i < isids_len; i++)
68 initial_sid_to_string[i] = stoupperx(initial_sid_to_string[i]);
69
70 fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
71 fprintf(fout, "#ifndef _SELINUX_FLASK_H_\n#define _SELINUX_FLASK_H_\n\n");
72
73 for (i = 0; secclass_map[i].name; i++) {
74 struct security_class_mapping *map = &secclass_map[i];
75 fprintf(fout, "#define SECCLASS_%s", map->name);
76 for (j = 0; j < max(1, 40 - strlen(map->name)); j++)
77 fprintf(fout, " ");
78 fprintf(fout, "%2d\n", i+1);
79 }
80
81 fprintf(fout, "\n");
82
83 for (i = 1; i < isids_len; i++) {
84 char *s = initial_sid_to_string[i];
85 fprintf(fout, "#define SECINITSID_%s", s);
86 for (j = 0; j < max(1, 40 - strlen(s)); j++)
87 fprintf(fout, " ");
88 fprintf(fout, "%2d\n", i);
89 }
90 fprintf(fout, "\n#define SECINITSID_NUM %d\n", i-1);
91 fprintf(fout, "\n#endif\n");
92 fclose(fout);
93
94 fout = fopen(argv[2], "w");
95 if (!fout) {
96 fprintf(stderr, "Could not open %s for writing: %s\n",
97 argv[2], strerror(errno));
98 exit(4);
99 }
100
101 fprintf(fout, "/* This file is automatically generated. Do not edit. */\n");
102 fprintf(fout, "#ifndef _SELINUX_AV_PERMISSIONS_H_\n#define _SELINUX_AV_PERMISSIONS_H_\n\n");
103
104 for (i = 0; secclass_map[i].name; i++) {
105 struct security_class_mapping *map = &secclass_map[i];
106 for (j = 0; map->perms[j]; j++) {
107 fprintf(fout, "#define %s__%s", map->name,
108 map->perms[j]);
109 for (k = 0; k < max(1, 40 - strlen(map->name) - strlen(map->perms[j])); k++)
110 fprintf(fout, " ");
111 fprintf(fout, "0x%08xUL\n", (1<<j));
112 }
113 }
114
115 fprintf(fout, "\n#endif\n");
116 fclose(fout);
117 exit(0);
118}
diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c
index b4ced8562587..62b34ce1f50d 100644
--- a/scripts/selinux/mdp/mdp.c
+++ b/scripts/selinux/mdp/mdp.c
@@ -29,86 +29,27 @@
29#include <unistd.h> 29#include <unistd.h>
30#include <string.h> 30#include <string.h>
31 31
32#include "flask.h"
33
34static void usage(char *name) 32static void usage(char *name)
35{ 33{
36 printf("usage: %s [-m] policy_file context_file\n", name); 34 printf("usage: %s [-m] policy_file context_file\n", name);
37 exit(1); 35 exit(1);
38} 36}
39 37
40static void find_common_name(char *cname, char *dest, int len) 38/* Class/perm mapping support */
41{ 39struct security_class_mapping {
42 char *start, *end; 40 const char *name;
43 41 const char *perms[sizeof(unsigned) * 8 + 1];
44 start = strchr(cname, '_')+1;
45 end = strchr(start, '_');
46 if (!start || !end || start-cname > len || end-start > len) {
47 printf("Error with commons defines\n");
48 exit(1);
49 }
50 strncpy(dest, start, end-start);
51 dest[end-start] = '\0';
52}
53
54#define S_(x) x,
55static char *classlist[] = {
56#include "class_to_string.h"
57 NULL
58}; 42};
59#undef S_
60 43
44#include "classmap.h"
61#include "initial_sid_to_string.h" 45#include "initial_sid_to_string.h"
62 46
63#define TB_(x) char *x[] = {
64#define TE_(x) NULL };
65#define S_(x) x,
66#include "common_perm_to_string.h"
67#undef TB_
68#undef TE_
69#undef S_
70
71struct common {
72 char *cname;
73 char **perms;
74};
75struct common common[] = {
76#define TB_(x) { #x, x },
77#define S_(x)
78#define TE_(x)
79#include "common_perm_to_string.h"
80#undef TB_
81#undef TE_
82#undef S_
83};
84
85#define S_(x, y, z) {x, #y},
86struct av_inherit {
87 int class;
88 char *common;
89};
90struct av_inherit av_inherit[] = {
91#include "av_inherit.h"
92};
93#undef S_
94
95#include "av_permissions.h"
96#define S_(x, y, z) {x, y, z},
97struct av_perms {
98 int class;
99 int perm_i;
100 char *perm_s;
101};
102struct av_perms av_perms[] = {
103#include "av_perm_to_string.h"
104};
105#undef S_
106
107int main(int argc, char *argv[]) 47int main(int argc, char *argv[])
108{ 48{
109 int i, j, mls = 0; 49 int i, j, mls = 0;
50 int initial_sid_to_string_len;
110 char **arg, *polout, *ctxout; 51 char **arg, *polout, *ctxout;
111 int classlist_len, initial_sid_to_string_len; 52
112 FILE *fout; 53 FILE *fout;
113 54
114 if (argc < 3) 55 if (argc < 3)
@@ -127,64 +68,25 @@ int main(int argc, char *argv[])
127 usage(argv[0]); 68 usage(argv[0]);
128 } 69 }
129 70
130 classlist_len = sizeof(classlist) / sizeof(char *);
131 /* print out the classes */ 71 /* print out the classes */
132 for (i=1; i < classlist_len; i++) { 72 for (i = 0; secclass_map[i].name; i++)
133 if(classlist[i]) 73 fprintf(fout, "class %s\n", secclass_map[i].name);
134 fprintf(fout, "class %s\n", classlist[i]);
135 else
136 fprintf(fout, "class user%d\n", i);
137 }
138 fprintf(fout, "\n"); 74 fprintf(fout, "\n");
139 75
140 initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *); 76 initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);
141 /* print out the sids */ 77 /* print out the sids */
142 for (i=1; i < initial_sid_to_string_len; i++) 78 for (i = 1; i < initial_sid_to_string_len; i++)
143 fprintf(fout, "sid %s\n", initial_sid_to_string[i]); 79 fprintf(fout, "sid %s\n", initial_sid_to_string[i]);
144 fprintf(fout, "\n"); 80 fprintf(fout, "\n");
145 81
146 /* print out the commons */
147 for (i=0; i< sizeof(common)/sizeof(struct common); i++) {
148 char cname[101];
149 find_common_name(common[i].cname, cname, 100);
150 cname[100] = '\0';
151 fprintf(fout, "common %s\n{\n", cname);
152 for (j=0; common[i].perms[j]; j++)
153 fprintf(fout, "\t%s\n", common[i].perms[j]);
154 fprintf(fout, "}\n\n");
155 }
156 fprintf(fout, "\n");
157
158 /* print out the class permissions */ 82 /* print out the class permissions */
159 for (i=1; i < classlist_len; i++) { 83 for (i = 0; secclass_map[i].name; i++) {
160 if (classlist[i]) { 84 struct security_class_mapping *map = &secclass_map[i];
161 int firstperm = -1, numperms = 0; 85 fprintf(fout, "class %s\n", map->name);
162 86 fprintf(fout, "{\n");
163 fprintf(fout, "class %s\n", classlist[i]); 87 for (j = 0; map->perms[j]; j++)
164 /* does it inherit from a common? */ 88 fprintf(fout, "\t%s\n", map->perms[j]);
165 for (j=0; j < sizeof(av_inherit)/sizeof(struct av_inherit); j++) 89 fprintf(fout, "}\n\n");
166 if (av_inherit[j].class == i)
167 fprintf(fout, "inherits %s\n", av_inherit[j].common);
168
169 for (j=0; j < sizeof(av_perms)/sizeof(struct av_perms); j++) {
170 if (av_perms[j].class == i) {
171 if (firstperm == -1)
172 firstperm = j;
173 numperms++;
174 }
175 }
176 if (!numperms) {
177 fprintf(fout, "\n");
178 continue;
179 }
180
181 fprintf(fout, "{\n");
182 /* print out the av_perms */
183 for (j=0; j < numperms; j++) {
184 fprintf(fout, "\t%s\n", av_perms[firstperm+j].perm_s);
185 }
186 fprintf(fout, "}\n\n");
187 }
188 } 90 }
189 fprintf(fout, "\n"); 91 fprintf(fout, "\n");
190 92
@@ -197,31 +99,34 @@ int main(int argc, char *argv[])
197 /* types, roles, and allows */ 99 /* types, roles, and allows */
198 fprintf(fout, "type base_t;\n"); 100 fprintf(fout, "type base_t;\n");
199 fprintf(fout, "role base_r types { base_t };\n"); 101 fprintf(fout, "role base_r types { base_t };\n");
200 for (i=1; i < classlist_len; i++) { 102 for (i = 0; secclass_map[i].name; i++)
201 if (classlist[i]) 103 fprintf(fout, "allow base_t base_t:%s *;\n",
202 fprintf(fout, "allow base_t base_t:%s *;\n", classlist[i]); 104 secclass_map[i].name);
203 else
204 fprintf(fout, "allow base_t base_t:user%d *;\n", i);
205 }
206 fprintf(fout, "user user_u roles { base_r };\n"); 105 fprintf(fout, "user user_u roles { base_r };\n");
207 fprintf(fout, "\n"); 106 fprintf(fout, "\n");
208 107
209 /* default sids */ 108 /* default sids */
210 for (i=1; i < initial_sid_to_string_len; i++) 109 for (i = 1; i < initial_sid_to_string_len; i++)
211 fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]); 110 fprintf(fout, "sid %s user_u:base_r:base_t\n", initial_sid_to_string[i]);
212 fprintf(fout, "\n"); 111 fprintf(fout, "\n");
213 112
214
215 fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n"); 113 fprintf(fout, "fs_use_xattr ext2 user_u:base_r:base_t;\n");
216 fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n"); 114 fprintf(fout, "fs_use_xattr ext3 user_u:base_r:base_t;\n");
115 fprintf(fout, "fs_use_xattr ext4 user_u:base_r:base_t;\n");
217 fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n"); 116 fprintf(fout, "fs_use_xattr jfs user_u:base_r:base_t;\n");
218 fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n"); 117 fprintf(fout, "fs_use_xattr xfs user_u:base_r:base_t;\n");
219 fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n"); 118 fprintf(fout, "fs_use_xattr reiserfs user_u:base_r:base_t;\n");
119 fprintf(fout, "fs_use_xattr jffs2 user_u:base_r:base_t;\n");
120 fprintf(fout, "fs_use_xattr gfs2 user_u:base_r:base_t;\n");
121 fprintf(fout, "fs_use_xattr lustre user_u:base_r:base_t;\n");
220 122
123 fprintf(fout, "fs_use_task eventpollfs user_u:base_r:base_t;\n");
221 fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n"); 124 fprintf(fout, "fs_use_task pipefs user_u:base_r:base_t;\n");
222 fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n"); 125 fprintf(fout, "fs_use_task sockfs user_u:base_r:base_t;\n");
223 126
127 fprintf(fout, "fs_use_trans mqueue user_u:base_r:base_t;\n");
224 fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n"); 128 fprintf(fout, "fs_use_trans devpts user_u:base_r:base_t;\n");
129 fprintf(fout, "fs_use_trans hugetlbfs user_u:base_r:base_t;\n");
225 fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n"); 130 fprintf(fout, "fs_use_trans tmpfs user_u:base_r:base_t;\n");
226 fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n"); 131 fprintf(fout, "fs_use_trans shm user_u:base_r:base_t;\n");
227 132