4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
30 #include <sys/types.h>
38 #include <netinet/in.h>
40 #if (defined(__SVR4) && defined(__sun)) || defined(__unleashed__)
41 /* Solaris has built-in SHA-1 and SHA-2 library interfaces */
46 * All others can use OpenSSL, but OpenSSL's method signatures
47 * are slightly different
49 #include <openssl/sha.h>
50 #define SHA1_CTX SHA_CTX
51 #define SHA1Update SHA1_Update
52 #define SHA1Init SHA1_Init
53 #define SHA1Final SHA1_Final
57 #include <elfextract.h>
60 pkg_string_from_type(int type
)
77 pkg_string_from_arch(int arch
)
87 #if defined(__SVR4) && defined(__sun)
88 /* Solaris calls x86_64 "amd64", and recognizes 486 */
104 pkg_string_from_data(int data
)
117 pkg_string_from_osabi(int osabi
)
121 /* case ELFOSABI_SYSV: */
125 case ELFOSABI_SOLARIS
:
137 if ((id
= malloc(EI_NIDENT
)) == NULL
) {
138 (void) PyErr_NoMemory();
142 if (lseek(fd
, 0, SEEK_SET
) == -1) {
143 PyErr_SetFromErrno(PyExc_IOError
);
148 if (read(fd
, id
, EI_NIDENT
) < 0) {
149 PyErr_SetFromErrno(PyExc_IOError
);
162 if (!(ident
= getident(fd
)))
165 if (strncmp(ident
, ELFMAG
, strlen(ELFMAG
)) == 0) {
179 if (!(ident
= getident(fd
)))
182 if (ident
[EI_CLASS
] == ELFCLASS32
) {
197 PyErr_SetString(PyExc_ValueError
,
198 "elf.so`gethead: argument 'elf' must not be NULL");
202 if ((hdr
= malloc(sizeof (GElf_Ehdr
))) == NULL
) {
203 (void) PyErr_NoMemory();
207 if (gelf_getehdr(elf
, hdr
) == 0) {
208 PyErr_SetString(ElfError
, elf_errmsg(-1));
217 getheaderinfo(int fd
)
223 if ((hi
= malloc(sizeof (hdrinfo_t
))) == NULL
) {
224 (void) PyErr_NoMemory();
228 if (elf_version(EV_CURRENT
) == EV_NONE
) {
229 PyErr_SetString(ElfError
, elf_errmsg(-1));
234 if (!(elf
= elf_begin(fd
, ELF_C_READ
, NULL
))) {
235 PyErr_SetString(ElfError
, elf_errmsg(-1));
240 if (!(hdr
= gethead(elf
))) {
246 hi
->type
= hdr
->e_type
;
247 hi
->bits
= hdr
->e_ident
[EI_CLASS
] == ELFCLASS32
? 32 : 64;
248 hi
->arch
= hdr
->e_machine
;
249 hi
->data
= hdr
->e_ident
[EI_DATA
];
250 hi
->osabi
= hdr
->e_ident
[EI_OSABI
];
259 * For ELF nontriviality: Need to turn an ELF object into a unique hash.
261 * From Eric Saxe's investigations, we see that the following sections can
262 * generally be ignored:
264 * .SUNW_signature, .comment, .SUNW_dof, .debug, .plt, .rela.bss,
265 * .rela.plt, .line, .note
267 * Conversely, the following sections are generally significant:
269 * .rodata.str1.8, .rodata.str1.1, .rodata, .data1, .data, .text
271 * Accordingly, we will hash on the latter group of sections to determine our
275 hashsection(char *name
)
277 if (strcmp(name
, ".SUNW_signature") == 0 ||
278 strcmp(name
, ".comment") == 0 ||
279 strcmp(name
, ".SUNW_dof") == 0 ||
280 strcmp(name
, ".debug") == 0 ||
281 strcmp(name
, ".plt") == 0 ||
282 strcmp(name
, ".rela.bss") == 0 ||
283 strcmp(name
, ".rela.plt") == 0 ||
284 strcmp(name
, ".line") == 0 ||
285 strcmp(name
, ".note") == 0 ||
286 strcmp(name
, ".compcom") == 0)
293 * Reads a section in 64k increments, adding it to the hash.
296 readhash(int fd
, SHA1_CTX
*shc
, SHA256_CTX
*shc2
, off_t offset
, off_t size
,
297 int sha1
, int sha256
)
300 char hashbuf
[64 * 1024];
306 if (lseek(fd
, offset
, SEEK_SET
) == -1) {
307 PyErr_SetFromErrno(PyExc_IOError
);
312 n
= MIN(size
, sizeof (hashbuf
));
313 if ((rbytes
= read(fd
, hashbuf
, n
)) == -1) {
314 PyErr_SetFromErrno(PyExc_IOError
);
318 SHA1Update(shc
, hashbuf
, rbytes
);
321 SHA256Update(shc2
, hashbuf
, rbytes
);
330 * getdynamic - returns a struct filled with the
331 * information we want from an ELF file. Returns NULL
332 * if it can't find everything (eg. not ELF file, wrong
333 * class of ELF file).
334 * If sha1 is > 0, we produce an SHA1 hash as part of the returned dictionary.
335 * If sha256 is > 0, we include an SHA2 256 hash in the returned dictionary.
338 getdynamic(int fd
, int sha1
, int sha256
)
343 Elf_Data
*data_dyn
= NULL
;
344 Elf_Data
*data_verneed
= NULL
, *data_verdef
= NULL
;
349 size_t vernum
= 0, verdefnum
= 0;
350 int t
= 0, num_dyn
= 0, dynstr
= -1;
354 dyninfo_t
*dyn
= NULL
;
356 liblist_t
*deps
= NULL
;
357 off_t rpath
= 0, runpath
= 0, def
= 0;
361 char *buf
= NULL
, *cp
= NULL
;
362 GElf_Verneed
*ev
= NULL
;
363 GElf_Vernaux
*ea
= NULL
;
364 liblist_t
*vers
= NULL
;
366 GElf_Verdef
*vd
= NULL
;
367 GElf_Verdaux
*va
= NULL
;
368 liblist_t
*verdef
= NULL
;
370 if (elf_version(EV_CURRENT
) == EV_NONE
) {
371 PyErr_SetString(ElfError
, elf_errmsg(-1));
375 if (!(elf
= elf_begin(fd
, ELF_C_READ
, NULL
))) {
376 PyErr_SetString(ElfError
, elf_errmsg(-1));
380 if (!elf_getshstrndx(elf
, &sh_str
)) {
381 PyErr_SetString(ElfError
, elf_errmsg(-1));
385 /* get useful sections */
392 while ((scn
= elf_nextscn(elf
, scn
))) {
393 if (gelf_getshdr(scn
, &shdr
) != &shdr
) {
394 PyErr_SetString(ElfError
, elf_errmsg(-1));
398 if (!(name
= elf_strptr(elf
, sh_str
, shdr
.sh_name
))) {
399 PyErr_SetString(ElfError
, elf_errmsg(-1));
403 if (hashsection(name
) && (sha1
> 0 || sha256
> 0)) {
404 if (shdr
.sh_type
== SHT_NOBITS
) {
406 * We can't just push shdr.sh_size into
407 * SHA1Update(), as its raw bytes will be
408 * different on x86 than they are on sparc.
409 * Convert to network byte-order first.
411 uint64_t n
= shdr
.sh_size
;
412 uint64_t mask
= 0xffffffff00000000ULL
;
413 uint32_t top
= htonl((uint32_t)((n
& mask
) >> 32));
414 uint32_t bot
= htonl((uint32_t)n
);
416 SHA1Update(&shc
, &top
, sizeof (top
));
417 SHA1Update(&shc
, &bot
, sizeof (bot
));
420 SHA256Update(&shc2
, &top
, sizeof (top
));
421 SHA256Update(&shc2
, &bot
, sizeof (bot
));
425 hash
= readhash(fd
, &shc
, &shc2
, shdr
.sh_offset
,
426 shdr
.sh_size
, sha1
, sha256
);
433 switch (shdr
.sh_type
) {
435 if (!(data_dyn
= elf_getdata(scn
, NULL
))) {
436 PyErr_SetString(ElfError
, elf_errmsg(-1));
440 num_dyn
= shdr
.sh_size
/ shdr
.sh_entsize
;
441 dynstr
= shdr
.sh_link
;
444 #ifdef SHT_SUNW_verdef
445 case SHT_SUNW_verdef
:
449 if (!(data_verdef
= elf_getdata(scn
, NULL
))) {
450 PyErr_SetString(ElfError
, elf_errmsg(-1));
454 verdefnum
= shdr
.sh_info
;
457 #ifdef SHT_SUNW_verneed
458 case SHT_SUNW_verneed
:
460 case SHT_GNU_verneed
:
462 if (!(data_verneed
= elf_getdata(scn
, NULL
))) {
463 PyErr_SetString(ElfError
, elf_errmsg(-1));
467 vernum
= shdr
.sh_info
;
472 /* Dynamic but no string table? */
473 if (data_dyn
&& dynstr
< 0) {
474 PyErr_SetString(ElfError
,
475 "bad elf: didn't find the dynamic duo");
479 /* Parse dynamic section */
480 if (!(deps
= liblist_alloc()))
483 for (t
= 0; t
< num_dyn
; t
++) {
484 if (gelf_getdyn(data_dyn
, t
, &gd
) == NULL
) {
485 PyErr_SetString(ElfError
, elf_errmsg(-1));
493 if (liblist_add(deps
, gd
.d_un
.d_val
) == NULL
)
497 rpath
= gd
.d_un
.d_val
;
500 runpath
= gd
.d_un
.d_val
;
503 if (gd
.d_un
.d_val
& DF_P1_DEFERRED
) {
509 /* Runpath supercedes rpath, but use rpath if no runpath */
514 * Finally, get version information for each item in
515 * our dependency list. This part is a little messier,
516 * as it seems that libelf / gelf do not implement this.
518 if (!(vers
= liblist_alloc()))
521 if (vernum
> 0 && data_verneed
) {
522 buf
= data_verneed
->d_buf
;
526 for (t
= 0; t
< vernum
; t
++) {
527 liblist_t
*veraux
= NULL
;
530 ev
= (GElf_Verneed
*)cp
;
532 if (!(veraux
= liblist_alloc()))
540 for (a
= 0; a
< ev
->vn_cnt
; a
++) {
543 ea
= (GElf_Vernaux
*)cp
;
544 if (liblist_add(veraux
, ea
->vna_name
) == NULL
)
548 if (liblist_add(vers
, ev
->vn_file
) == NULL
)
550 vers
->tail
->verlist
= veraux
;
555 /* Consolidate version and dependency information */
556 if (liblist_foreach(deps
, setver_liblist_cb
, vers
, NULL
) == -1)
562 * Now, figure out what versions we provide.
565 if (!(verdef
= liblist_alloc()))
568 if (verdefnum
> 0 && data_verdef
) {
569 buf
= data_verdef
->d_buf
;
573 for (t
= 0; t
< verdefnum
; t
++) {
576 vd
= (GElf_Verdef
*)cp
;
582 for (a
= 0; a
< vd
->vd_cnt
; a
++) {
585 va
= (GElf_Verdaux
*)cp
;
586 /* first one is name, rest are versions */
589 else if (liblist_add(verdef
, va
->vda_name
) == NULL
)
596 if ((dyn
= malloc(sizeof (dyninfo_t
))) == NULL
) {
597 (void) PyErr_NoMemory();
601 dyn
->runpath
= runpath
;
602 dyn
->dynstr
= dynstr
;
608 SHA1Final(dyn
->hash
, &shc
);
611 SHA256Final(dyn
->hash256
, &shc2
);
619 liblist_free(verdef
);
628 dyninfo_free(dyninfo_t
*dyn
)
630 liblist_free(dyn
->deps
);
631 liblist_free(dyn
->vers
);
632 (void) elf_end(dyn
->elf
);