summaryrefslogtreecommitdiffstats
path: root/meta
diff options
context:
space:
mode:
authorMark Hatle <mark.hatle@windriver.com>2011-06-20 10:57:49 -0500
committerRichard Purdie <richard.purdie@linuxfoundation.org>2011-06-30 22:54:04 +0100
commit8781c843cf3e0913a8fdd2ff91935f051be01dd9 (patch)
treeab22da12fdc2d43bf13f0b18e92c5eee2d155781 /meta
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')
-rw-r--r--meta/classes/package.bbclass253
-rw-r--r--meta/files/fs-perms.txt69
2 files changed, 312 insertions, 10 deletions
diff --git a/meta/classes/package.bbclass b/meta/classes/package.bbclass
index 8f91c95ca6..0161c68054 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
diff --git a/meta/files/fs-perms.txt b/meta/files/fs-perms.txt
new file mode 100644
index 0000000000..f5a2b696e0
--- /dev/null
+++ b/meta/files/fs-perms.txt
@@ -0,0 +1,69 @@
1# This file contains a list of files and directories with known permissions.
2# It is used by the packaging class to ensure that the permissions, owners and
3# group of listed files and directories are in sync across the system.
4#
5# The format of this file
6#
7#<path> <mode> <uid> <gid> <walk> <fmode> <fuid> <fgid>
8#
9# or
10#
11#<path> link <target>
12#
13# <path>: directory path
14# <mode>: mode for directory
15# <uid>: uid for directory
16# <gid>: gid for directory
17# <walk>: recursively walk the directory? true or false
18# <fmode>: if walking, new mode for files
19# <fuid>: if walking, new uid for files
20# <fgid>: if walking, new gid for files
21# <target>: turn the directory into a symlink point to target
22#
23# in mode, uid or gid, a "-" means don't change any existing values
24#
25# /usr/src 0755 root root false - - -
26# /usr/share/man 0755 root root true 0644 root root
27
28# Note: all standard config directories are automatically assigned "0755 root root false - - -"
29
30# Documentation should always be corrected
31${mandir} 0755 root root true 0644 root root
32${infodir} 0755 root root true 0644 root root
33${docdir} 0755 root root true 0644 root root
34${datadir}/gtk-doc 0755 root root true 0644 root root
35
36# Fixup locales
37${datadir}/locale 0755 root root true 0644 root root
38
39# Cleanup headers
40${includedir} 0755 root root true 0644 root root
41${oldincludedir} 0755 root root true 0644 root root
42
43# Cleanup debug src
44/usr/src/debug 0755 root root true 0644 root root
45
46# Items from base-files
47# Links
48${localstatedir}/cache link volatile/cache
49${localstatedir}/run link volatile/run
50${localstatedir}/log link volatile/log
51${localstatedir}/lock link volatile/lock
52${localstatedir}/tmp link volatile/tmp
53
54# Special permissions from base-files
55# Set 1777
56/tmp 01777 root root false - - -
57${localstatedir}/volatile/lock 01777 root root false - - -
58${localstatedir}/volatile/tmp 01777 root root false - - -
59
60# Set 2775
61/home 02755 root root false - - -
62${prefix}/src 02755 root root false - - -
63${localstatedir}/local 02755 root root false - - -
64
65# Set 3755
66/srv 0755 root root false - - -
67
68# Set 4775
69/var/mail 02755 root root false - - -