linux-yocto/scripts/patch-kernel
Greg Kroah-Hartman b24413180f License cleanup: add SPDX GPL-2.0 license identifier to files with no license
Many source files in the tree are missing licensing information, which
makes it harder for compliance tools to determine the correct license.

By default all files without license information are under the default
license of the kernel, which is GPL version 2.

Update the files which contain no license information with the 'GPL-2.0'
SPDX license identifier.  The SPDX identifier is a legally binding
shorthand, which can be used instead of the full boiler plate text.

This patch is based on work done by Thomas Gleixner and Kate Stewart and
Philippe Ombredanne.

How this work was done:

Patches were generated and checked against linux-4.14-rc6 for a subset of
the use cases:
 - file had no licensing information it it.
 - file was a */uapi/* one with no licensing information in it,
 - file was a */uapi/* one with existing licensing information,

Further patches will be generated in subsequent months to fix up cases
where non-standard license headers were used, and references to license
had to be inferred by heuristics based on keywords.

The analysis to determine which SPDX License Identifier to be applied to
a file was done in a spreadsheet of side by side results from of the
output of two independent scanners (ScanCode & Windriver) producing SPDX
tag:value files created by Philippe Ombredanne.  Philippe prepared the
base worksheet, and did an initial spot review of a few 1000 files.

The 4.13 kernel was the starting point of the analysis with 60,537 files
assessed.  Kate Stewart did a file by file comparison of the scanner
results in the spreadsheet to determine which SPDX license identifier(s)
to be applied to the file. She confirmed any determination that was not
immediately clear with lawyers working with the Linux Foundation.

Criteria used to select files for SPDX license identifier tagging was:
 - Files considered eligible had to be source code files.
 - Make and config files were included as candidates if they contained >5
   lines of source
 - File already had some variant of a license header in it (even if <5
   lines).

All documentation files were explicitly excluded.

The following heuristics were used to determine which SPDX license
identifiers to apply.

 - when both scanners couldn't find any license traces, file was
   considered to have no license information in it, and the top level
   COPYING file license applied.

   For non */uapi/* files that summary was:

   SPDX license identifier                            # files
   ---------------------------------------------------|-------
   GPL-2.0                                              11139

   and resulted in the first patch in this series.

   If that file was a */uapi/* path one, it was "GPL-2.0 WITH
   Linux-syscall-note" otherwise it was "GPL-2.0".  Results of that was:

   SPDX license identifier                            # files
   ---------------------------------------------------|-------
   GPL-2.0 WITH Linux-syscall-note                        930

   and resulted in the second patch in this series.

 - if a file had some form of licensing information in it, and was one
   of the */uapi/* ones, it was denoted with the Linux-syscall-note if
   any GPL family license was found in the file or had no licensing in
   it (per prior point).  Results summary:

   SPDX license identifier                            # files
   ---------------------------------------------------|------
   GPL-2.0 WITH Linux-syscall-note                       270
   GPL-2.0+ WITH Linux-syscall-note                      169
   ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause)    21
   ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)    17
   LGPL-2.1+ WITH Linux-syscall-note                      15
   GPL-1.0+ WITH Linux-syscall-note                       14
   ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause)    5
   LGPL-2.0+ WITH Linux-syscall-note                       4
   LGPL-2.1 WITH Linux-syscall-note                        3
   ((GPL-2.0 WITH Linux-syscall-note) OR MIT)              3
   ((GPL-2.0 WITH Linux-syscall-note) AND MIT)             1

   and that resulted in the third patch in this series.

 - when the two scanners agreed on the detected license(s), that became
   the concluded license(s).

 - when there was disagreement between the two scanners (one detected a
   license but the other didn't, or they both detected different
   licenses) a manual inspection of the file occurred.

 - In most cases a manual inspection of the information in the file
   resulted in a clear resolution of the license that should apply (and
   which scanner probably needed to revisit its heuristics).

 - When it was not immediately clear, the license identifier was
   confirmed with lawyers working with the Linux Foundation.

 - If there was any question as to the appropriate license identifier,
   the file was flagged for further research and to be revisited later
   in time.

In total, over 70 hours of logged manual review was done on the
spreadsheet to determine the SPDX license identifiers to apply to the
source files by Kate, Philippe, Thomas and, in some cases, confirmation
by lawyers working with the Linux Foundation.

Kate also obtained a third independent scan of the 4.13 code base from
FOSSology, and compared selected files where the other two scanners
disagreed against that SPDX file, to see if there was new insights.  The
Windriver scanner is based on an older version of FOSSology in part, so
they are related.

Thomas did random spot checks in about 500 files from the spreadsheets
for the uapi headers and agreed with SPDX license identifier in the
files he inspected. For the non-uapi files Thomas did random spot checks
in about 15000 files.

In initial set of patches against 4.14-rc6, 3 files were found to have
copy/paste license identifier errors, and have been fixed to reflect the
correct identifier.

Additionally Philippe spent 10 hours this week doing a detailed manual
inspection and review of the 12,461 patched files from the initial patch
version early this week with:
 - a full scancode scan run, collecting the matched texts, detected
   license ids and scores
 - reviewing anything where there was a license detected (about 500+
   files) to ensure that the applied SPDX license was correct
 - reviewing anything where there was no detection but the patch license
   was not GPL-2.0 WITH Linux-syscall-note to ensure that the applied
   SPDX license was correct

This produced a worksheet with 20 files needing minor correction.  This
worksheet was then exported into 3 different .csv files for the
different types of files to be modified.

These .csv files were then reviewed by Greg.  Thomas wrote a script to
parse the csv files and add the proper SPDX tag to the file, in the
format that the file expected.  This script was further refined by Greg
based on the output to detect more types of files automatically and to
distinguish between header and source .c files (which need different
comment types.)  Finally Greg ran the script using the .csv files to
generate the patches.

Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-11-02 11:10:55 +01:00

9.9 KiB
Executable File

#! /bin/sh

SPDX-License-Identifier: GPL-2.0

Script to apply kernel patches.

usage: patch-kernel [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ]

The source directory defaults to /usr/src/linux, and the patch

directory defaults to the current directory.

e.g.

scripts/patch-kernel . ..

Update the kernel tree in the current directory using patches in the

directory above to the latest Linus kernel

scripts/patch-kernel . .. -ac

Get the latest Linux kernel and patch it with the latest ac patch

scripts/patch-kernel . .. 2.4.9

Gets standard kernel 2.4.9

scripts/patch-kernel . .. 2.4.9 -ac

Gets 2.4.9 with latest ac patches

scripts/patch-kernel . .. 2.4.9 -ac11

Gets 2.4.9 with ac patch ac11

Note: It uses the patches relative to the Linus kernels, not the

ac to ac relative patches

It determines the current kernel version from the top-level Makefile.

It then looks for patches for the next sublevel in the patch directory.

This is applied using "patch -p1 -s" from within the kernel directory.

A check is then made for "*.rej" files to see if the patch was

successful. If it is, then all of the "*.orig" files are removed.

Nick Holloway Nick.Holloway@alfie.demon.co.uk, 2nd January 1995.

Added support for handling multiple types of compression. What includes

gzip, bzip, bzip2, zip, compress, and plaintext.

Adam Sulmicki adam@cfar.umd.edu, 1st January 1997.

Added ability to stop at a given version number

Put the full version number (i.e. 2.3.31) as the last parameter

Dave Gilbert linux@treblig.org, 11th December 1999.

Fixed previous patch so that if we are already at the correct version

not to patch up.

Added -ac option, use -ac or -ac9 (say) to stop at a particular version

Dave Gilbert linux@treblig.org, 29th September 2001.

Add support for (use of) EXTRAVERSION (to support 2.6.8.x, e.g.);

update usage message;

fix some whitespace damage;

be smarter about stopping when current version is larger than requested;

Randy Dunlap rdunlap@xenotime.net, 2004-AUG-18.

Add better support for (non-incremental) 2.6.x.y patches;

If an ending version number if not specified, the script automatically

increments the SUBLEVEL (x in 2.6.x.y) until no more patch files are found;

however, EXTRAVERSION (y in 2.6.x.y) is never automatically incremented

but must be specified fully.

patch-kernel does not normally support reverse patching, but does so when

applying EXTRAVERSION (x.y) patches, so that moving from 2.6.11.y to 2.6.11.z

is easy and handled by the script (reverse 2.6.11.y and apply 2.6.11.z).

Randy Dunlap rdunlap@xenotime.net, 2005-APR-08.

PNAME=patch-kernel

Set directories from arguments, or use defaults.

sourcedir=${1-/usr/src/linux} patchdir=${2-.} stopvers=${3-default}

if [ "$1" = -h -o "$1" = --help -o ! -r "$sourcedir/Makefile" ]; then cat << USAGE usage: $PNAME [-h] [ sourcedir [ patchdir [ stopversion ] [ -acxx ] ] ] source directory defaults to /usr/src/linux, patch directory defaults to the current directory, stopversion defaults to . USAGE exit 1 fi

See if we have any -ac options

for PARM in $* do case $PARM in -ac*) gotac=$PARM;

esac;

done

---------------------------------------------------------------------------

arg1 is filename

noFile () { echo "cannot find patch file: ${patch}" exit 1 }

---------------------------------------------------------------------------

backwards () { echo "$PNAME does not support reverse patching" exit 1 }

---------------------------------------------------------------------------

Find a file, first parameter is basename of file

it tries many compression mechanisms and sets variables to say how to get it

findFile () { filebase=$1;

if [ -r ${filebase}.gz ]; then ext=".gz" name="gzip" uncomp="gunzip -dc" elif [ -r ${filebase}.bz ]; then ext=".bz" name="bzip" uncomp="bunzip -dc" elif [ -r ${filebase}.bz2 ]; then ext=".bz2" name="bzip2" uncomp="bunzip2 -dc" elif [ -r ${filebase}.xz ]; then ext=".xz" name="xz" uncomp="xz -dc" elif [ -r ${filebase}.zip ]; then ext=".zip" name="zip" uncomp="unzip -d" elif [ -r ${filebase}.Z ]; then ext=".Z" name="uncompress" uncomp="uncompress -c" elif [ -r ${filebase} ]; then ext="" name="plaintext" uncomp="cat" else return 1; fi

return 0; }

---------------------------------------------------------------------------

Apply a patch and check it goes in cleanly

First param is patch name (e.g. patch-2.4.9-ac5) - without path or extension

applyPatch () { echo -n "Applying $1 (${name})... " if $uncomp ${patchdir}/$1${ext} | patch -p1 -s -N -E -d $sourcedir then echo "done." else echo "failed. Clean up yourself." return 1; fi if [ "find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print" ] then echo "Aborting. Reject files found." return 1; fi

Remove backup files

find $sourcedir/ '(' -name '.orig' -o -name '..orig' ')' -exec rm -f {} ;

return 0; }

---------------------------------------------------------------------------

arg1 is patch filename

reversePatch () { echo -n "Reversing $1 (${name}) ... " if $uncomp ${patchdir}/"$1"${ext} | patch -p1 -Rs -N -E -d $sourcedir then echo "done." else echo "failed. Clean it up." exit 1 fi if [ "find $sourcedir/ '(' -name '*.rej' -o -name '.*.rej' ')' -print" ] then echo "Aborting. Reject files found." return 1 fi # Remove backup files find $sourcedir/ '(' -name '.orig' -o -name '..orig' ')' -exec rm -f {} ;

return 0

}

set current VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION

force $TMPFILEs below to be in local directory: a slash character prevents

the dot command from using the search path.

TMPFILE=mktemp ./.tmpver.XXXXXX || { echo "cannot make temp file" ; exit 1; } grep -E "^(VERSION|PATCHLEVEL|SUBLEVEL|EXTRAVERSION)" $sourcedir/Makefile > $TMPFILE tr -d [:blank:] < $TMPFILE > $TMPFILE.1 . $TMPFILE.1 rm -f $TMPFILE* if [ -z "$VERSION" -o -z "$PATCHLEVEL" -o -z "$SUBLEVEL" ] then echo "unable to determine current kernel version" >&2 exit 1 fi

NAME=grep ^NAME $sourcedir/Makefile NAME=${NAME##*=}

echo "Current kernel version is $VERSION.$PATCHLEVEL.$SUBLEVEL${EXTRAVERSION} ($NAME)"

strip EXTRAVERSION to just a number (drop leading '.' and trailing additions)

EXTRAVER= if [ x$EXTRAVERSION != "x" ] then EXTRAVER=${EXTRAVERSION#.} EXTRAVER=${EXTRAVER%%:punct:*} #echo "$PNAME: changing EXTRAVERSION from $EXTRAVERSION to $EXTRAVER" fi

#echo "stopvers=$stopvers" if [ $stopvers != "default" ]; then STOPSUBLEVEL=echo $stopvers | cut -d. -f3 STOPEXTRA=echo $stopvers | cut -d. -f4 STOPFULLVERSION=${stopvers%%.$STOPEXTRA} #echo "#___STOPSUBLEVEL=/$STOPSUBLEVEL/, STOPEXTRA=/$STOPEXTRA/" else STOPSUBLEVEL=9999 STOPEXTRA=9999 fi

This all assumes a 2.6.x[.y] kernel tree.

Don't allow backwards/reverse patching.

if [ $STOPSUBLEVEL -lt $SUBLEVEL ]; then backwards fi

if [ x$EXTRAVER != "x" ]; then CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$EXTRAVER" else CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" fi

if [ x$EXTRAVER != "x" ]; then echo "backing up to: $VERSION.$PATCHLEVEL.$SUBLEVEL" patch="patch-${CURRENTFULLVERSION}" findFile $patchdir/${patch} || noFile ${patch} reversePatch ${patch} || exit 1 fi

now current is 2.6.x, with no EXTRA applied,

so update to target SUBLEVEL (2.6.SUBLEVEL)

and then to target EXTRAVER (2.6.SUB.EXTRAVER) if requested.

If not ending sublevel is specified, it is incremented until

no further sublevels are found.

if [ $STOPSUBLEVEL -gt $SUBLEVEL ]; then while : # incrementing SUBLEVEL (s in v.p.s) do CURRENTFULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL" EXTRAVER= if [ x$STOPFULLVERSION = x$CURRENTFULLVERSION ]; then echo "Stopping at $CURRENTFULLVERSION base as requested." break fi

SUBLEVEL=$(($SUBLEVEL + 1))
FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL"
#echo "#___ trying $FULLVERSION ___"

if [ $(($SUBLEVEL)) -gt $(($STOPSUBLEVEL)) ]; then
echo "Stopping since sublevel ($SUBLEVEL) is beyond stop-sublevel ($STOPSUBLEVEL)"
exit 1
fi

patch=patch-$FULLVERSION
# See if the file exists and find extension
findFile $patchdir/${patch} || noFile ${patch}

# Apply the patch and check all is OK
applyPatch $patch || break

done #echo "#___sublevel all done" fi

There is no incremental searching for extraversion...

if [ "$STOPEXTRA" != "" ]; then while : # just to allow break do

apply STOPEXTRA directly (not incrementally) (x in v.p.s.x)

FULLVERSION="$VERSION.$PATCHLEVEL.$SUBLEVEL.$STOPEXTRA"
#echo "#... trying $FULLVERSION ..."
patch=patch-$FULLVERSION

# See if the file exists and find extension
findFile $patchdir/${patch} || noFile ${patch}

# Apply the patch and check all is OK
applyPatch $patch || break
#echo "#___extraver all done"
break

done fi

if [ x$gotac != x ]; then

Out great user wants the -ac patches

# They could have done -ac (get latest) or -acxx where xx=version they want
if [ $gotac = "-ac" ]; then
  # They want the latest version
	HIGHESTPATCH=0
	for PATCHNAMES in $patchdir/patch-${CURRENTFULLVERSION}-ac*\.*
	do
		ACVALUE=`echo $PATCHNAMES | sed -e 's/^.*patch-[0-9.]*-ac\([0-9]*\).*/\1/'`
		# Check it is actually a recognised patch type
		findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${ACVALUE} || break

	  if [ $ACVALUE -gt $HIGHESTPATCH ]; then
		  HIGHESTPATCH=$ACVALUE
	  fi
	done

	if [ $HIGHESTPATCH -ne 0 ]; then
		findFile $patchdir/patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH} || break
		applyPatch patch-${CURRENTFULLVERSION}-ac${HIGHESTPATCH}
	else
	  echo "No -ac patches found"
	fi
else
  # They want an exact version
	findFile $patchdir/patch-${CURRENTFULLVERSION}${gotac} || {
	  echo "Sorry, I couldn't find the $gotac patch for $CURRENTFULLVERSION.  Hohum."
		exit 1
	}
	applyPatch patch-${CURRENTFULLVERSION}${gotac}
fi

fi