https://github.com/torvalds/linux
Revision dd4d747ef05addab887dc8ff0d6ab9860bbcd783 authored by Nadezda Lutovinova on 21 September 2021, 15:51:53 UTC, committed by Guenter Roeck on 02 October 2021, 12:14:11 UTC
If driver read tmp value sufficient for (tmp & 0x08) && (!(tmp & 0x80)) && ((tmp & 0x7) == ((tmp >> 4) & 0x7)) from device then Null pointer dereference occurs. (It is possible if tmp = 0b0xyz1xyz, where same literals mean same numbers) Also lm75[] does not serve a purpose anymore after switching to devm_i2c_new_dummy_device() in w83791d_detect_subclients(). The patch fixes possible NULL pointer dereference by removing lm75[]. Found by Linux Driver Verification project (linuxtesting.org). Cc: stable@vger.kernel.org Signed-off-by: Nadezda Lutovinova <lutovinova@ispras.ru> Link: https://lore.kernel.org/r/20210921155153.28098-3-lutovinova@ispras.ru [groeck: Dropped unnecessary continuation lines, fixed multi-line alignments] Signed-off-by: Guenter Roeck <linux@roeck-us.net>
1 parent 0f36b88
Tip revision: dd4d747ef05addab887dc8ff0d6ab9860bbcd783 authored by Nadezda Lutovinova on 21 September 2021, 15:51:53 UTC
hwmon: (w83793) Fix NULL pointer dereference by removing unnecessary structure field
hwmon: (w83793) Fix NULL pointer dereference by removing unnecessary structure field
Tip revision: dd4d747
generate_initcall_order.pl
#!/usr/bin/env perl
# SPDX-License-Identifier: GPL-2.0
#
# Generates a linker script that specifies the correct initcall order.
#
# Copyright (C) 2019 Google LLC
use strict;
use warnings;
use IO::Handle;
use IO::Select;
use POSIX ":sys_wait_h";
my $nm = $ENV{'NM'} || die "$0: ERROR: NM not set?";
my $objtree = $ENV{'objtree'} || '.';
## currently active child processes
my $jobs = {}; # child process pid -> file handle
## results from child processes
my $results = {}; # object index -> [ { level, secname }, ... ]
## reads _NPROCESSORS_ONLN to determine the maximum number of processes to
## start
sub get_online_processors {
open(my $fh, "getconf _NPROCESSORS_ONLN 2>/dev/null |")
or die "$0: ERROR: failed to execute getconf: $!";
my $procs = <$fh>;
close($fh);
if (!($procs =~ /^\d+$/)) {
return 1;
}
return int($procs);
}
## writes results to the parent process
## format: <file index> <initcall level> <base initcall section name>
sub write_results {
my ($index, $initcalls) = @_;
# sort by the counter value to ensure the order of initcalls within
# each object file is correct
foreach my $counter (sort { $a <=> $b } keys(%{$initcalls})) {
my $level = $initcalls->{$counter}->{'level'};
# section name for the initcall function
my $secname = $initcalls->{$counter}->{'module'} . '__' .
$counter . '_' .
$initcalls->{$counter}->{'line'} . '_' .
$initcalls->{$counter}->{'function'};
print "$index $level $secname\n";
}
}
## reads a result line from a child process and adds it to the $results array
sub read_results{
my ($fh) = @_;
# each child prints out a full line w/ autoflush and exits after the
# last line, so even if buffered I/O blocks here, it shouldn't block
# very long
my $data = <$fh>;
if (!defined($data)) {
return 0;
}
chomp($data);
my ($index, $level, $secname) = $data =~
/^(\d+)\ ([^\ ]+)\ (.*)$/;
if (!defined($index) ||
!defined($level) ||
!defined($secname)) {
die "$0: ERROR: child process returned invalid data: $data\n";
}
$index = int($index);
if (!exists($results->{$index})) {
$results->{$index} = [];
}
push (@{$results->{$index}}, {
'level' => $level,
'secname' => $secname
});
return 1;
}
## finds initcalls from an object file or all object files in an archive, and
## writes results back to the parent process
sub find_initcalls {
my ($index, $file) = @_;
die "$0: ERROR: file $file doesn't exist?" if (! -f $file);
open(my $fh, "\"$nm\" --defined-only \"$file\" 2>/dev/null |")
or die "$0: ERROR: failed to execute \"$nm\": $!";
my $initcalls = {};
while (<$fh>) {
chomp;
# check for the start of a new object file (if processing an
# archive)
my ($path)= $_ =~ /^(.+)\:$/;
if (defined($path)) {
write_results($index, $initcalls);
$initcalls = {};
next;
}
# look for an initcall
my ($module, $counter, $line, $symbol) = $_ =~
/[a-z]\s+__initcall__(\S*)__(\d+)_(\d+)_(.*)$/;
if (!defined($module)) {
$module = ''
}
if (!defined($counter) ||
!defined($line) ||
!defined($symbol)) {
next;
}
# parse initcall level
my ($function, $level) = $symbol =~
/^(.*)((early|rootfs|con|[0-9])s?)$/;
die "$0: ERROR: invalid initcall name $symbol in $file($path)"
if (!defined($function) || !defined($level));
$initcalls->{$counter} = {
'module' => $module,
'line' => $line,
'function' => $function,
'level' => $level,
};
}
close($fh);
write_results($index, $initcalls);
}
## waits for any child process to complete, reads the results, and adds them to
## the $results array for later processing
sub wait_for_results {
my ($select) = @_;
my $pid = 0;
do {
# unblock children that may have a full write buffer
foreach my $fh ($select->can_read(0)) {
read_results($fh);
}
# check for children that have exited, read the remaining data
# from them, and clean up
$pid = waitpid(-1, WNOHANG);
if ($pid > 0) {
if (!exists($jobs->{$pid})) {
next;
}
my $fh = $jobs->{$pid};
$select->remove($fh);
while (read_results($fh)) {
# until eof
}
close($fh);
delete($jobs->{$pid});
}
} while ($pid > 0);
}
## forks a child to process each file passed in the command line and collects
## the results
sub process_files {
my $index = 0;
my $njobs = $ENV{'PARALLELISM'} || get_online_processors();
my $select = IO::Select->new();
while (my $file = shift(@ARGV)) {
# fork a child process and read it's stdout
my $pid = open(my $fh, '-|');
if (!defined($pid)) {
die "$0: ERROR: failed to fork: $!";
} elsif ($pid) {
# save the child process pid and the file handle
$select->add($fh);
$jobs->{$pid} = $fh;
} else {
# in the child process
STDOUT->autoflush(1);
find_initcalls($index, "$objtree/$file");
exit;
}
$index++;
# limit the number of children to $njobs
if (scalar(keys(%{$jobs})) >= $njobs) {
wait_for_results($select);
}
}
# wait for the remaining children to complete
while (scalar(keys(%{$jobs})) > 0) {
wait_for_results($select);
}
}
sub generate_initcall_lds() {
process_files();
my $sections = {}; # level -> [ secname, ...]
# sort results to retain link order and split to sections per
# initcall level
foreach my $index (sort { $a <=> $b } keys(%{$results})) {
foreach my $result (@{$results->{$index}}) {
my $level = $result->{'level'};
if (!exists($sections->{$level})) {
$sections->{$level} = [];
}
push(@{$sections->{$level}}, $result->{'secname'});
}
}
die "$0: ERROR: no initcalls?" if (!keys(%{$sections}));
# print out a linker script that defines the order of initcalls for
# each level
print "SECTIONS {\n";
foreach my $level (sort(keys(%{$sections}))) {
my $section;
if ($level eq 'con') {
$section = '.con_initcall.init';
} else {
$section = ".initcall${level}.init";
}
print "\t${section} : {\n";
foreach my $secname (@{$sections->{$level}}) {
print "\t\t*(${section}..${secname}) ;\n";
}
print "\t}\n";
}
print "}\n";
}
generate_initcall_lds();
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...