summaryrefslogtreecommitdiffstats
path: root/meta/classes/package.bbclass
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@windriver.com>2011-06-20 15:57:49 (GMT)
committerRichard Purdie <richard.purdie@linuxfoundation.org>2011-06-30 21:54:04 (GMT)
commit8781c843cf3e0913a8fdd2ff91935f051be01dd9 (patch)
treeab22da12fdc2d43bf13f0b18e92c5eee2d155781 /meta/classes/package.bbclass
parentb78173f176eeff553e2e941bd06ff032daebc7be (diff)
downloadpoky-8781c843cf3e0913a8fdd2ff91935f051be01dd9.tar.gz
classes/package.bbclass: Add fixup_perms
Add a new function that is responsible for fixing directory and file permissions, owners and groups during the packaging process. This will fix various issues where two packages may create the same directory and end up with different permissions, owner and/or group. The issue being resolved is that if two packages conflict in their ownership of a directory, the first installed into the rootfs sets the permissions. This leads to a least potentially non-deterministic filesystems, at worst security defects. The user can specify their own settings via the configuration files specified in FILESYSTEM_PERMS_TABLES. If this is not defined, it will fall back to loading files/fs-perms.txt from BBPATH. The format of this file is documented within the file. By default all of the system directories, specified in bitbake.conf, will be fixed to be 0755, root, root. The fs-perms.txt contains a few default entries to correct documentation, locale, headers and debug sources. It was discovered these are often incorrect due to being directly copied from the build user environment. The entries needed to match the base-files package have also been added. Also tweak a couple of warnings to provide more diagnostic information. (From OE-Core rev: 8c720efa053f81dc8d2bb604cdbdb25de9a6efab) Signed-off-by: Mark Hatle <mark.hatle@windriver.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/classes/package.bbclass')
-rw-r--r--meta/classes/package.bbclass253
1 files changed, 243 insertions, 10 deletions
diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass
index 8f91c95..0161c68 100644
--- a/meta/classes/package.bbclass
+++ b/meta/classes/package.bbclass
@@ -16,24 +16,26 @@
16# d) split_and_strip_files - split the files into runtime and debug and strip them. 16# d) split_and_strip_files - split the files into runtime and debug and strip them.
17# Debug files include debug info split, and associated sources that end up in -dbg packages 17# Debug files include debug info split, and associated sources that end up in -dbg packages
18# 18#
19# e) populate_packages - Split the files in PKGD into separate packages in PKGDEST/<pkgname> 19# e) fixup_perms - Fix up permissions in the package before we split it.
20#
21# f) populate_packages - Split the files in PKGD into separate packages in PKGDEST/<pkgname>
20# Also triggers the binary stripping code to put files in -dbg packages. 22# Also triggers the binary stripping code to put files in -dbg packages.
21# 23#
22# f) package_do_filedeps - Collect perfile run-time dependency metadata 24# g) package_do_filedeps - Collect perfile run-time dependency metadata
23# The data is stores in FILER{PROVIDES,DEPENDS}_file_pkg variables with 25# The data is stores in FILER{PROVIDES,DEPENDS}_file_pkg variables with
24# a list of affected files in FILER{PROVIDES,DEPENDS}FLIST_pkg 26# a list of affected files in FILER{PROVIDES,DEPENDS}FLIST_pkg
25# 27#
26# g) package_do_shlibs - Look at the shared libraries generated and autotmatically add any 28# h) package_do_shlibs - Look at the shared libraries generated and autotmatically add any
27# depenedencies found. Also stores the package name so anyone else using this library 29# depenedencies found. Also stores the package name so anyone else using this library
28# knows which package to depend on. 30# knows which package to depend on.
29# 31#
30# h) package_do_pkgconfig - Keep track of which packages need and provide which .pc files 32# i) package_do_pkgconfig - Keep track of which packages need and provide which .pc files
31# 33#
32# i) read_shlibdeps - Reads the stored shlibs information into the metadata 34# j) read_shlibdeps - Reads the stored shlibs information into the metadata
33# 35#
34# j) package_depchains - Adds automatic dependencies to -dbg and -dev packages 36# k) package_depchains - Adds automatic dependencies to -dbg and -dev packages
35# 37#
36# k) emit_pkgdata - saves the packaging data into PKGDATA_DIR for use in later 38# l) emit_pkgdata - saves the packaging data into PKGDATA_DIR for use in later
37# packaging steps 39# packaging steps
38 40
39inherit packagedata 41inherit packagedata
@@ -237,7 +239,7 @@ def splitfile2(debugsrcdir, d):
237 # We need to ignore files that are not actually ours 239 # We need to ignore files that are not actually ours
238 # we do this by only paying attention to items from this package 240 # we do this by only paying attention to items from this package
239 processdebugsrc += "fgrep -z '%s' | " 241 processdebugsrc += "fgrep -z '%s' | "
240 processdebugsrc += "(cd '%s' ; cpio -pd0mL '%s%s' 2>/dev/null)" 242 processdebugsrc += "(cd '%s' ; cpio -pd0mL --no-preserve-owner '%s%s' 2>/dev/null)"
241 243
242 os.system(processdebugsrc % (sourcefile, workbasedir, workparentdir, dvar, debugsrcdir)) 244 os.system(processdebugsrc % (sourcefile, workbasedir, workparentdir, dvar, debugsrcdir))
243 245
@@ -410,10 +412,239 @@ python perform_packagecopy () {
410 os.system('tar -cf - -C %s -ps . | tar -xf - -C %s' % (dest, dvar)) 412 os.system('tar -cf - -C %s -ps . | tar -xf - -C %s' % (dest, dvar))
411} 413}
412 414
415# We generate a master list of directories to process, we start by
416# seeding this list with reasonable defaults, then load from
417# the fs-perms.txt files
418python fixup_perms () {
419 import os, pwd, grp
420
421 # init using a string with the same format as a line as documented in
422 # the fs-perms.txt file
423 # <path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid>
424 # <path> link <link target>
425 #
426 # __str__ can be used to print out an entry in the input format
427 #
428 # if fs_perms_entry.path is None:
429 # an error occured
430 # if fs_perms_entry.link, you can retrieve:
431 # fs_perms_entry.path = path
432 # fs_perms_entry.link = target of link
433 # if not fs_perms_entry.link, you can retrieve:
434 # fs_perms_entry.path = path
435 # fs_perms_entry.mode = expected dir mode or None
436 # fs_perms_entry.uid = expected uid or -1
437 # fs_perms_entry.gid = expected gid or -1
438 # fs_perms_entry.walk = 'true' or something else
439 # fs_perms_entry.fmode = expected file mode or None
440 # fs_perms_entry.fuid = expected file uid or -1
441 # fs_perms_entry_fgid = expected file gid or -1
442 class fs_perms_entry():
443 def __init__(self, line):
444 lsplit = line.split()
445 if len(lsplit) == 3 and lsplit[1].lower() == "link":
446 self._setlink(lsplit[0], lsplit[2])
447 elif len(lsplit) == 8:
448 self._setdir(lsplit[0], lsplit[1], lsplit[2], lsplit[3], lsplit[4], lsplit[5], lsplit[6], lsplit[7])
449 else:
450 bb.error("Fixup Perms: invalid config line %s" % line)
451 self.path = None
452 self.link = None
453
454 def _setdir(self, path, mode, uid, gid, walk, fmode, fuid, fgid):
455 self.path = os.path.normpath(path)
456 self.link = None
457 self.mode = self._procmode(mode)
458 self.uid = self._procuid(uid)
459 self.gid = self._procgid(gid)
460 self.walk = walk.lower()
461 self.fmode = self._procmode(fmode)
462 self.fuid = self._procuid(fuid)
463 self.fgid = self._procgid(fgid)
464
465 def _setlink(self, path, link):
466 self.path = os.path.normpath(path)
467 self.link = link
468
469 def _procmode(self, mode):
470 if not mode or (mode and mode == "-"):
471 return None
472 else:
473 return int(mode,8)
474
475 # Note uid/gid -1 has special significance in os.chown
476 def _procuid(self, uid):
477 if uid is None or uid == "-":
478 return -1
479 elif uid.isdigit():
480 return int(uid)
481 else:
482 return pwd.getpwnam(uid).pw_uid
483
484 def _procgid(self, gid):
485 if gid is None or gid == "-":
486 return -1
487 elif gid.isdigit():
488 return int(gid)
489 else:
490 return grp.getgrnam(gid).gr_gid
491
492 # Use for debugging the entries
493 def __str__(self):
494 if self.link:
495 return "%s link %s" % (self.path, self.link)
496 else:
497 mode = "-"
498 if self.mode:
499 mode = "0%o" % self.mode
500 fmode = "-"
501 if self.fmode:
502 fmode = "0%o" % self.fmode
503 uid = self._mapugid(self.uid)
504 gid = self._mapugid(self.gid)
505 fuid = self._mapugid(self.fuid)
506 fgid = self._mapugid(self.fgid)
507 return "%s %s %s %s %s %s %s %s" % (self.path, mode, uid, gid, self.walk, fmode, fuid, fgid)
508
509 def _mapugid(self, id):
510 if id is None or id == -1:
511 return "-"
512 else:
513 return "%d" % id
514
515 # Fix the permission, owner and group of path
516 def fix_perms(path, mode, uid, gid, dir):
517 if mode:
518 #bb.note("Fixup Perms: chmod 0%o %s" % (mode, dir))
519 os.chmod(path, mode)
520 # -1 is a special value that means don't change the uid/gid
521 # if they are BOTH -1, don't bother to chown
522 if not (uid == -1 and gid == -1):
523 #bb.note("Fixup Perms: chown %d:%d %s" % (uid, gid, dir))
524 os.chown(path, uid, gid)
525
526 # Return a list of configuration files based on either the default
527 # files/fs-perms.txt or the contents of FILESYSTEM_PERMS_TABLES
528 # paths are resolved via BBPATH
529 def get_fs_perms_list(d):
530 str = ""
531 fs_perms_tables = bb.data.getVar('FILESYSTEM_PERMS_TABLES', d, True)
532 if not fs_perms_tables:
533 fs_perms_tables = 'files/fs-perms.txt'
534 for conf_file in fs_perms_tables.split():
535 str += " %s" % bb.which(bb.data.getVar('BBPATH', d, True), conf_file)
536 return str
537
538
539
540 dvar = bb.data.getVar('PKGD', d, True)
541
542 fs_perms_table = {}
543
544 # By default all of the standard directories specified in
545 # bitbake.conf will get 0755 root:root.
546 target_path_vars = [ 'base_prefix',
547 'prefix',
548 'exec_prefix',
549 'base_bindir',
550 'base_sbindir',
551 'base_libdir',
552 'datadir',
553 'sysconfdir',
554 'servicedir',
555 'sharedstatedir',
556 'localstatedir',
557 'infodir',
558 'mandir',
559 'docdir',
560 'bindir',
561 'sbindir',
562 'libexecdir',
563 'libdir',
564 'includedir',
565 'oldincludedir' ]
566
567 for path in target_path_vars:
568 dir = bb.data.getVar(path, d, True) or ""
569 if dir == "":
570 continue
571 fs_perms_table[dir] = fs_perms_entry(bb.data.expand("%s 0755 root root false - - -" % (dir), d))
572
573 # Now we actually load from the configuration files
574 for conf in get_fs_perms_list(d).split():
575 if os.path.exists(conf):
576 f = open(conf)
577 for line in f:
578 if line.startswith('#'):
579 continue
580 lsplit = line.split()
581 if len(lsplit) == 0:
582 continue
583 if len(lsplit) != 8 and not (len(lsplit) == 3 and lsplit[1].lower() == "link"):
584 bb.error("Fixup perms: %s invalid line: %s" % (conf, line))
585 continue
586 entry = fs_perms_entry(bb.data.expand(line, d))
587 if entry and entry.path:
588 fs_perms_table[entry.path] = entry
589 f.close()
590
591 # Debug -- list out in-memory table
592 #for dir in fs_perms_table:
593 # bb.note("Fixup Perms: %s: %s" % (dir, str(fs_perms_table[dir])))
594
595 # We process links first, so we can go back and fixup directory ownership
596 # for any newly created directories
597 for dir in fs_perms_table:
598 if not fs_perms_table[dir].link:
599 continue
600
601 origin = dvar + dir
602 if not (os.path.exists(origin) and os.path.isdir(origin) and not os.path.islink(origin)):
603 continue
604
605 link = fs_perms_table[dir].link
606 if link[0] == "/":
607 target = dvar + link
608 ptarget = link
609 else:
610 target = os.path.join(os.path.dirname(origin), link)
611 ptarget = os.path.join(os.path.dirname(dir), link)
612 if os.path.exists(target):
613 bb.error("Fixup Perms: Unable to correct directory link, target already exists: %s -> %s" % (dir, ptarget))
614 continue
615
616 # Create path to move directory to, move it, and then setup the symlink
617 bb.mkdirhier(os.path.dirname(target))
618 #bb.note("Fixup Perms: Rename %s -> %s" % (dir, ptarget))
619 os.rename(origin, target)
620 #bb.note("Fixup Perms: Link %s -> %s" % (dir, link))
621 os.symlink(link, origin)
622
623 for dir in fs_perms_table:
624 if fs_perms_table[dir].link:
625 continue
626
627 origin = dvar + dir
628 if not (os.path.exists(origin) and os.path.isdir(origin)):
629 continue
630
631 fix_perms(origin, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
632
633 if fs_perms_table[dir].walk == 'true':
634 for root, dirs, files in os.walk(origin):
635 for dr in dirs:
636 each_dir = os.path.join(root, dr)
637 fix_perms(each_dir, fs_perms_table[dir].mode, fs_perms_table[dir].uid, fs_perms_table[dir].gid, dir)
638 for f in files:
639 each_file = os.path.join(root, f)
640 fix_perms(each_file, fs_perms_table[dir].fmode, fs_perms_table[dir].fuid, fs_perms_table[dir].fgid, dir)
641}
642
413python split_and_strip_files () { 643python split_and_strip_files () {
414 import commands, stat, errno 644 import commands, stat, errno
415 645
416 dvar = bb.data.getVar('PKGD', d, True) 646 dvar = bb.data.getVar('PKGD', d, True)
647 pn = bb.data.getVar('PN', d, True)
417 648
418 # We default to '.debug' style 649 # We default to '.debug' style
419 if bb.data.getVar('PACKAGE_DEBUG_SPLIT_STYLE', d, True) == 'debug-file-directory': 650 if bb.data.getVar('PACKAGE_DEBUG_SPLIT_STYLE', d, True) == 'debug-file-directory':
@@ -551,7 +782,7 @@ python split_and_strip_files () {
551 if file_list[file].startswith("ELF: "): 782 if file_list[file].startswith("ELF: "):
552 elf_file = int(file_list[file][5:]) 783 elf_file = int(file_list[file][5:])
553 if elf_file & 2: 784 if elf_file & 2:
554 bb.warn("File '%s' was already stripped, this will prevent future debugging!" % (src)) 785 bb.warn("File '%s' from %s was already stripped, this will prevent future debugging!" % (src, pn))
555 continue 786 continue
556 787
557 # Split the file... 788 # Split the file...
@@ -690,7 +921,7 @@ python populate_packages () {
690 unshipped.append(path) 921 unshipped.append(path)
691 922
692 if unshipped != []: 923 if unshipped != []:
693 bb.warn("the following files were installed but not shipped in any package:") 924 bb.warn("the following files were installed but not shipped in any package: %s" % pn)
694 for f in unshipped: 925 for f in unshipped:
695 bb.warn(" " + f) 926 bb.warn(" " + f)
696 927
@@ -1373,6 +1604,7 @@ PACKAGEFUNCS ?= "package_get_auto_pr \
1373 ${PACKAGE_PREPROCESS_FUNCS} \ 1604 ${PACKAGE_PREPROCESS_FUNCS} \
1374 package_do_split_locales \ 1605 package_do_split_locales \
1375 split_and_strip_files \ 1606 split_and_strip_files \
1607 fixup_perms \
1376 populate_packages \ 1608 populate_packages \
1377 package_do_filedeps \ 1609 package_do_filedeps \
1378 package_do_shlibs \ 1610 package_do_shlibs \
@@ -1400,6 +1632,7 @@ python do_package () {
1400 for f in (bb.data.getVar('PACKAGEFUNCS', d, True) or '').split(): 1632 for f in (bb.data.getVar('PACKAGEFUNCS', d, True) or '').split():
1401 bb.build.exec_func(f, d) 1633 bb.build.exec_func(f, d)
1402} 1634}
1635
1403do_package[dirs] = "${SHLIBSWORKDIR} ${PKGDESTWORK} ${D}" 1636do_package[dirs] = "${SHLIBSWORKDIR} ${PKGDESTWORK} ${D}"
1404addtask package before do_build after do_install 1637addtask package before do_build after do_install
1405 1638