[01/23] buildhistory.bbclass: add LICENSE and CVE_PRODUCT to recipe and package data

Submitted by Mikko Rapeli on July 20, 2017, 1:22 p.m. | Patch ID: 142161

Details

Message ID 1500556991-11471-2-git-send-email-mikko.rapeli@bmw.de
State New
Headers show

Commit Message

Mikko Rapeli July 20, 2017, 1:22 p.m.
LICENSE can be used in various checks after builds. Reading license data
from buildhistory is better than trying to parse recipes in a source tree.

CVE_PRODUCT can be used by scripts to e.g. check if it matches to the
CVE product names in CVE/NVD database.

It the two are combined, a CVE product name check can for example ignore
recipes with CLOSED license.

Note about sstate caching: recipe and package buildhistory data is
regenarated only when the recipe is rebuild from sources. New fields
like LICENSE and CVE_PRODUCT in buildhistory will be deployed only after
the recipes are recompiled.

Example:

$ bitbake -c cleanall busybox && bitbake busybox
$ egrep "LICENSE|CVE_PRODUCT" buildhistory/packages/i586-poky-linux/busybox/busybox/latest
LICENSE = GPLv2 & bzip2
CVE_PRODUCT = busybox

Signed-off-by: Mikko Rapeli <mikko.rapeli@bmw.de>
---
 meta/classes/buildhistory.bbclass | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

Patch hide | download patch | download mbox

diff --git a/meta/classes/buildhistory.bbclass b/meta/classes/buildhistory.bbclass
index 81784ee..cc3b144 100644
--- a/meta/classes/buildhistory.bbclass
+++ b/meta/classes/buildhistory.bbclass
@@ -92,6 +92,8 @@  python buildhistory_emit_pkghistory() {
             self.packages = ""
             self.srcrev = ""
             self.layer = ""
+            self.license = ""
+            self.cve_product = ""
 
 
     class PackageInfo:
@@ -105,6 +107,8 @@  python buildhistory_emit_pkghistory() {
             self.pkge = ""
             self.pkgv = ""
             self.pkgr = ""
+            self.license = ""
+            self.cve_product = ""
             self.size = 0
             self.depends = ""
             self.rprovides = ""
@@ -141,6 +145,10 @@  python buildhistory_emit_pkghistory() {
                     pkginfo.pkgv = value
                 elif name == "PKGR":
                     pkginfo.pkgr = value
+                elif name == "LICENSE":
+                    pkginfo.license = value
+                elif name == "CVE_PRODUCT":
+                    pkginfo.cve_product = value
                 elif name == "RPROVIDES":
                     pkginfo.rprovides = value
                 elif name == "RDEPENDS":
@@ -193,6 +201,9 @@  python buildhistory_emit_pkghistory() {
     pv = d.getVar('PV')
     pr = d.getVar('PR')
     layer = bb.utils.get_file_layer(d.getVar('FILE', True), d)
+    license = d.getVar('LICENSE') or ''
+    # If recipe does not define CVE_PRODUCT, the default is pn
+    cve_product = d.getVar('CVE_PRODUCT') or pn
 
     pkgdata_dir = d.getVar('PKGDATA_DIR')
     packages = ""
@@ -233,6 +244,8 @@  python buildhistory_emit_pkghistory() {
     rcpinfo.depends = sortlist(oe.utils.squashspaces(d.getVar('DEPENDS') or ""))
     rcpinfo.packages = packages
     rcpinfo.layer = layer
+    rcpinfo.license = license
+    rcpinfo.cve_product = cve_product
     write_recipehistory(rcpinfo, d)
 
     pkgdest = d.getVar('PKGDEST')
@@ -249,6 +262,8 @@  python buildhistory_emit_pkghistory() {
         pkge = pkgdata.get('PKGE', '0')
         pkgv = pkgdata['PKGV']
         pkgr = pkgdata['PKGR']
+        pkg_license = d.getVar('LICENSE_%s' % (pkg,), True) or license
+        pkg_cve_product = d.getVar('CVE_PRODUCT_%s' % (pkg,), True) or cve_product
         #
         # Find out what the last version was
         # Make sure the version did not decrease
@@ -272,6 +287,8 @@  python buildhistory_emit_pkghistory() {
         pkginfo.pkge = pkge
         pkginfo.pkgv = pkgv
         pkginfo.pkgr = pkgr
+        pkginfo.license = pkg_license
+        pkginfo.cve_product = pkg_cve_product
         pkginfo.rprovides = sortpkglist(oe.utils.squashspaces(pkgdata.get('RPROVIDES', "")))
         pkginfo.rdepends = sortpkglist(oe.utils.squashspaces(pkgdata.get('RDEPENDS', "")))
         pkginfo.rrecommends = sortpkglist(oe.utils.squashspaces(pkgdata.get('RRECOMMENDS', "")))
@@ -347,6 +364,8 @@  def write_recipehistory(rcpinfo, d):
         f.write(u"DEPENDS = %s\n" %  rcpinfo.depends)
         f.write(u"PACKAGES = %s\n" %  rcpinfo.packages)
         f.write(u"LAYER = %s\n" %  rcpinfo.layer)
+        f.write(u"LICENSE = %s\n" % rcpinfo.license)
+        f.write(u"CVE_PRODUCT = %s\n" % rcpinfo.cve_product)
 
     write_latest_srcrev(d, pkghistdir)
 
@@ -374,6 +393,8 @@  def write_pkghistory(pkginfo, d):
             f.write(u"PKGV = %s\n" % pkginfo.pkgv)
         if pkginfo.pkgr != pkginfo.pr:
             f.write(u"PKGR = %s\n" % pkginfo.pkgr)
+        f.write(u"LICENSE = %s\n" % pkginfo.license)
+        f.write(u"CVE_PRODUCT = %s\n" % pkginfo.cve_product)
         f.write(u"RPROVIDES = %s\n" %  pkginfo.rprovides)
         f.write(u"RDEPENDS = %s\n" %  pkginfo.rdepends)
         f.write(u"RRECOMMENDS = %s\n" %  pkginfo.rrecommends)

Comments

Mikko Rapeli Aug. 2, 2017, 7:38 a.m.
On Thu, Jul 20, 2017 at 04:22:49PM +0300, Mikko Rapeli wrote:
> LICENSE can be used in various checks after builds. Reading license data
> from buildhistory is better than trying to parse recipes in a source tree.
> 
> CVE_PRODUCT can be used by scripts to e.g. check if it matches to the
> CVE product names in CVE/NVD database.
> 
> It the two are combined, a CVE product name check can for example ignore
> recipes with CLOSED license.
> 
> Note about sstate caching: recipe and package buildhistory data is
> regenarated only when the recipe is rebuild from sources. New fields
> like LICENSE and CVE_PRODUCT in buildhistory will be deployed only after
> the recipes are recompiled.
> 
> Example:
> 
> $ bitbake -c cleanall busybox && bitbake busybox
> $ egrep "LICENSE|CVE_PRODUCT" buildhistory/packages/i586-poky-linux/busybox/busybox/latest
> LICENSE = GPLv2 & bzip2
> CVE_PRODUCT = busybox

Are there some problems with this approach? Is CVE_PRODUCT too much?

I find this much better than trying to parse recipes for the data, and I like
that history data of these variables across builds/releases is available.

-Mikko

> Signed-off-by: Mikko Rapeli <mikko.rapeli@bmw.de>
> ---
>  meta/classes/buildhistory.bbclass | 21 +++++++++++++++++++++
>  1 file changed, 21 insertions(+)
> 
> diff --git a/meta/classes/buildhistory.bbclass b/meta/classes/buildhistory.bbclass
> index 81784ee..cc3b144 100644
> --- a/meta/classes/buildhistory.bbclass
> +++ b/meta/classes/buildhistory.bbclass
> @@ -92,6 +92,8 @@ python buildhistory_emit_pkghistory() {
>              self.packages = ""
>              self.srcrev = ""
>              self.layer = ""
> +            self.license = ""
> +            self.cve_product = ""
>  
>  
>      class PackageInfo:
> @@ -105,6 +107,8 @@ python buildhistory_emit_pkghistory() {
>              self.pkge = ""
>              self.pkgv = ""
>              self.pkgr = ""
> +            self.license = ""
> +            self.cve_product = ""
>              self.size = 0
>              self.depends = ""
>              self.rprovides = ""
> @@ -141,6 +145,10 @@ python buildhistory_emit_pkghistory() {
>                      pkginfo.pkgv = value
>                  elif name == "PKGR":
>                      pkginfo.pkgr = value
> +                elif name == "LICENSE":
> +                    pkginfo.license = value
> +                elif name == "CVE_PRODUCT":
> +                    pkginfo.cve_product = value
>                  elif name == "RPROVIDES":
>                      pkginfo.rprovides = value
>                  elif name == "RDEPENDS":
> @@ -193,6 +201,9 @@ python buildhistory_emit_pkghistory() {
>      pv = d.getVar('PV')
>      pr = d.getVar('PR')
>      layer = bb.utils.get_file_layer(d.getVar('FILE', True), d)
> +    license = d.getVar('LICENSE') or ''
> +    # If recipe does not define CVE_PRODUCT, the default is pn
> +    cve_product = d.getVar('CVE_PRODUCT') or pn
>  
>      pkgdata_dir = d.getVar('PKGDATA_DIR')
>      packages = ""
> @@ -233,6 +244,8 @@ python buildhistory_emit_pkghistory() {
>      rcpinfo.depends = sortlist(oe.utils.squashspaces(d.getVar('DEPENDS') or ""))
>      rcpinfo.packages = packages
>      rcpinfo.layer = layer
> +    rcpinfo.license = license
> +    rcpinfo.cve_product = cve_product
>      write_recipehistory(rcpinfo, d)
>  
>      pkgdest = d.getVar('PKGDEST')
> @@ -249,6 +262,8 @@ python buildhistory_emit_pkghistory() {
>          pkge = pkgdata.get('PKGE', '0')
>          pkgv = pkgdata['PKGV']
>          pkgr = pkgdata['PKGR']
> +        pkg_license = d.getVar('LICENSE_%s' % (pkg,), True) or license
> +        pkg_cve_product = d.getVar('CVE_PRODUCT_%s' % (pkg,), True) or cve_product
>          #
>          # Find out what the last version was
>          # Make sure the version did not decrease
> @@ -272,6 +287,8 @@ python buildhistory_emit_pkghistory() {
>          pkginfo.pkge = pkge
>          pkginfo.pkgv = pkgv
>          pkginfo.pkgr = pkgr
> +        pkginfo.license = pkg_license
> +        pkginfo.cve_product = pkg_cve_product
>          pkginfo.rprovides = sortpkglist(oe.utils.squashspaces(pkgdata.get('RPROVIDES', "")))
>          pkginfo.rdepends = sortpkglist(oe.utils.squashspaces(pkgdata.get('RDEPENDS', "")))
>          pkginfo.rrecommends = sortpkglist(oe.utils.squashspaces(pkgdata.get('RRECOMMENDS', "")))
> @@ -347,6 +364,8 @@ def write_recipehistory(rcpinfo, d):
>          f.write(u"DEPENDS = %s\n" %  rcpinfo.depends)
>          f.write(u"PACKAGES = %s\n" %  rcpinfo.packages)
>          f.write(u"LAYER = %s\n" %  rcpinfo.layer)
> +        f.write(u"LICENSE = %s\n" % rcpinfo.license)
> +        f.write(u"CVE_PRODUCT = %s\n" % rcpinfo.cve_product)
>  
>      write_latest_srcrev(d, pkghistdir)
>  
> @@ -374,6 +393,8 @@ def write_pkghistory(pkginfo, d):
>              f.write(u"PKGV = %s\n" % pkginfo.pkgv)
>          if pkginfo.pkgr != pkginfo.pr:
>              f.write(u"PKGR = %s\n" % pkginfo.pkgr)
> +        f.write(u"LICENSE = %s\n" % pkginfo.license)
> +        f.write(u"CVE_PRODUCT = %s\n" % pkginfo.cve_product)
>          f.write(u"RPROVIDES = %s\n" %  pkginfo.rprovides)
>          f.write(u"RDEPENDS = %s\n" %  pkginfo.rdepends)
>          f.write(u"RRECOMMENDS = %s\n" %  pkginfo.rrecommends)
> -- 
> 1.9.1