Dynamic linking

栏目: IT技术 · 发布时间: 6年前

内容简介:Findings:Over half of your libraries are used by fewer than 0.1% of your executables.

Do your installed programs share dynamic libraries?

Findings: not really

Over half of your libraries are used by fewer than 0.1% of your executables. Dynamic linking Number of times each dynamic library is required by a program

libs.awk

/\t.*\.so.*/ {
	n=split($1, p, "/")
	split(p[n], l, ".")
	lib=l[1]
	if (libs[lib] == "") {
		libs[lib] = 0
	}
	libs[lib] += 1
}
END {
	for (lib in libs) {
		print libs[lib] "\t" lib
	}
}

Usage

$ find /usr/bin -type f -executable -print \
  | xargs ldd 2>/dev/null \
  | awk -f libs.awk \
  | sort -rn > results.txt
$ awk '{ print NR "\t" $1 }' < results.txt > nresults.txt
$ gnuplot
gnuplot> plot 'nresults.txt'

my results

$ find /usr/bin -type f -executable -print | wc -l
5688
$ head -n20 < results.txt
4496	libc
4484	linux-vdso
4483	ld-linux-x86-64
2654	libm
2301	libdl
2216	libpthread
1419	libgcc_s
1301	libz
1144	libstdc++
805	liblzma
785	librt
771	libXdmcp
771	libxcb
771	libXau
755	libX11
703	libpcre
667	libglib-2
658	libffi
578	libresolv
559	libXext

Is loading dynamically linked programs faster?

Findings: definitely not

Linkage Avg. startup time
Dynamic 137263 ns
Static 64048 ns

ex.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	fprintf(stdout, "%ld\t", ts.tv_nsec);
	fflush(stdout);
	if (argc == 1) {
		char *args[] = { "", "", NULL };
		execvp(argv[0], args);
	} else {
		fprintf(stdout, "\n");
	}
	return 0;
}

test.sh

#!/bin/sh
i=0
while [ $i -lt 1000 ]
do
	./ex
	i=$((i+1))
done

My results

$ musl-gcc -o ex ex.c
$ ./test.sh | awk 'BEGIN { sum = 0 } { sum += $2-$1 } END { print sum / NR }'
137263
$ musl-gcc -static -o ex ex.c
$ ./test.sh | awk 'BEGIN { sum = 0 } { sum += $2-$1 } END { print sum / NR }'
64048

Wouldn't statically linked executables be huge?

Findings: not really

On average, dynamically linked executables use only 4.6% of the symbols on offer from their dependencies. A good linker will remove unused symbols. Dynamic linking % of symbols requested by dynamically linked programs from the libraries that it depends on

nsyms.go

package main

import (
	"bufio"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
)

func main() {
	ldd := exec.Command("ldd", os.Args[1])
	rc, err := ldd.StdoutPipe()
	if err != nil {
		panic(err)
	}
	ldd.Start()

	var libpaths []string
	scan := bufio.NewScanner(rc)
	for scan.Scan() {
		line := scan.Text()[1:] /* \t */
		sp := strings.Split(line, " ")
		var lib string
		if strings.Contains(line, "=>") {
			lib = sp[2]
		} else {
			lib = sp[0]
		}
		if !filepath.IsAbs(lib) {
			lib = "/usr/lib/" + lib
		}
		libpaths = append(libpaths, lib)
	}
	ldd.Wait()
	rc.Close()

	syms := make(map[string]interface{})
	for _, path := range libpaths {
		objdump := exec.Command("objdump", "-T", path)
		rc, err := objdump.StdoutPipe()
		if err != nil {
			panic(err)
		}
		objdump.Start()
		scan := bufio.NewScanner(rc)
		for i := 0; scan.Scan(); i++ {
			if i < 4 {
				continue
			}
			line := scan.Text()
			sp := strings.Split(line, " ")
			if len(sp) < 5 {
				continue
			}
			sym := sp[len(sp)-1]
			syms[sym] = nil
		}
		objdump.Wait()
		rc.Close()
	}

	objdump := exec.Command("objdump", "-R", os.Args[1])
	rc, err = objdump.StdoutPipe()
	if err != nil {
		panic(err)
	}
	objdump.Start()
	used := make(map[string]interface{})
	scan = bufio.NewScanner(rc)
	for i := 0; scan.Scan(); i++ {
		if i < 5 {
			continue
		}
		sp := strings.Split(scan.Text(), " ")
		if len(sp) < 3 {
			continue
		}
		sym := sp[len(sp)-1]
		used[sym] = nil
	}
	objdump.Wait()
	rc.Close()

	if len(syms) != 0 && len(used) != 0 && len(used) <= len(syms) {
		fmt.Printf("%50s\t%d\t%d\t%f\n", os.Args[1], len(syms), len(used),
			float64(len(used)) / float64(len(syms)))
	}
}

Usage

$ find /usr/bin -type f -executable -print | xargs -n1 ./nsyms > results.txt
$ awk '{ n += $4 } END { print n / NR }' < results.txt

my results

Will security vulnerabilities in libraries that have been statically linked cause large or unmanagable updates?

Findings: not really

Not including libc, the only libraries which had "critical" or "high" severity vulnerabilities in 2019 which affected over 100 binaries on my system were dbus, gnutls, cairo, libssh2, and curl. 265 binaries were affected by the rest.

The total download cost to upgrade all binaries on my system which were affected by these CVEs in 2019 is 3.8 GiB. This is reduced to 1.0 GiB if you eliminate glibc.

It is also unknown if any of these vulnerabilities would have been introduced after the last build date for a given statically linked binary; if so that binary would not need to be updated. Many vulnerabilities are also limited to a specific code path or use-case, and binaries which do not invoke that code path in their dependencies will not be affected. A process to ascertain this information in the wake of a vulnerability could be automated.

arch-security

extractcves.py

import email.utils
import mailbox
import re
import shlex
import time

pacman_re = re.compile(r'pacman -Syu .*')
severity_re = re.compile(r'Severity: (.*)')

mbox = mailbox.mbox("arch-security.mbox")
for m in mbox.items():
    m = m[1]
    date = m["Date"]
    for part in m.walk():
        if part.is_multipart():
            continue
        content_type = part.get_content_type()
        [charset] = part.get_charsets("utf-8")
        if content_type == 'text/plain':
            body = part.get_payload(decode=True).decode(charset)
            break
    pkgs = pacman_re.findall(body)
    severity = severity_re.findall(body)
    date = email.utils.parsedate(date)
    if len(pkgs) == 0 or date is None:
        continue
    if date[0] <= 2018 or date[0] > 2019:
        continue
    severity = severity[0]
    args = shlex.split(pkgs[0])
    pkg = args[2].split(">=")[0]
    print(pkg, severity)
$ python3 extractcves.py | grep Critical > cves.txt
$ xargs pacman -Ql < cves.txt | grep \\.so | awk '{print $1}' | sort -u>affected.txt
# Manually remove packages like Firefox, Thunderbird, etc; write remainder.txt
$ xargs pacman -Ql < remainder.txt | grep '/usr/lib/.*.so$' | awk '{ print $2 }' > libs.txt
$ ldd /usr/bin/* >ldd.txt
$ ./scope.sh <libs.txt | sort -nr >sobjects.txt

sobjects.txt is a sorted list of shared objects and the number of executables that link to them. To find the total size of affected binaries, I ran the following command:

# With libc
$ egrep -la 'libc.so|libm.so|libdl.so|libpthread.so|librt.so|libresolv.so|libdbus-1.so|libgnutls.so|libcairo.so|libutil.so|libssh2.so|libcurl.so|libcairo-gobject.so|libcrypt.so|libspice-server.so|libarchive.so|libSDL2-2.0.so|libmvec.so|libmagic.so|libtextstyle.so|libgettextlib-0.20.2.so|libgettextsrc-0.20.2.so|libMagickWand-7.Q16HDRI.so|libMagickCore-7.Q16HDRI.so|libbfd-2.34.0.so|libpolkit-gobject-1.so|libwebkit2gtk-4.0.so|libjavascriptcoregtk-4.0.so|libpolkit-agent-1.so|libgs.so|libctf.so|libSDL.so|libopcodes-2.34.0.so|libQt5WebEngine.so|libQt5WebEngineCore.so|libctf-nobfd.so|libcairo-script-interpreter.so' /usr/bin/* | xargs wc -c
# Without libc
$ egrep -la 'libdbus-1.so|libgnutls.so|libcairo.so|libssh2.so|libcurl.so|libcairo-gobject.so|libcrypt.so|libspice-server.so|libarchive.so|libSDL2-2.0.so|libmvec.so|libmagic.so|libtextstyle.so|libgettextlib-0.20.2.so|libgettextsrc-0.20.2.so|libMagickWand-7.Q16HDRI.so|libMagickCore-7.Q16HDRI.so|libbfd-2.34.0.so|libpolkit-gobject-1.so|libwebkit2gtk-4.0.so|libjavascriptcoregtk-4.0.so|libpolkit-agent-1.so|libgs.so|libctf.so|libSDL.so|libopcodes-2.34.0.so|libQt5WebEngine.so|libQt5WebEngineCore.so|libctf-nobfd.so|libcairo-script-interpreter.so' /usr/bin/* | xargs wc -c

Test environment

  • Arch Linux, up-to-date as of 2020-06-25
  • 2188 packages installed
  • gcc 10.1.0

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

数据库系统实现

数据库系统实现

加西亚-莫利纳(Hector Garcia-Molina)、Jeffrey D.Ullman、Jennifer Widom / 杨冬青、吴愈青、包小源 / 机械工业出版社 / 2010-5 / 59.00元

《数据库系统实现(第2版)》是斯坦福大学计算机科学专业数据库系列课程第二门课的教科书。书中对数据库系统实现原理进行了深入阐述,并具体讨论了数据库管理系统的三个主要成分——存储管理器、查询处理器和事务管理器的实现技术。此外,第2版充分反映了数据管理技术的新进展,对内容进行了扩充,除了在第1版中原有的“信息集成”一章(第10章)中加入了新的内容外,还增加了两个全新的章:“数据挖掘”(第11章)和“数据......一起来看看 《数据库系统实现》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具