/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <libelf.h>
#include <gelf.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <inttypes.h>
/* Solaris has built-in SHA-1 and SHA-2 library interfaces */
#include <sha1.h>
#include <sha2.h>
#else
/*
* All others can use OpenSSL, but OpenSSL's method signatures
* are slightly different
*/
#endif
#include <liblist.h>
#include <elfextract.h>
char *
{
switch (type) {
case ET_EXEC:
return ("exe");
case ET_DYN:
return ("so");
case ET_CORE:
return ("core");
case ET_REL:
return ("rel");
default:
return ("other");
}
}
char *
{
switch (arch) {
case EM_NONE:
return ("none");
case EM_SPARC:
case EM_SPARC32PLUS:
case EM_SPARCV9:
return ("sparc");
case EM_386:
/* Solaris calls x86_64 "amd64", and recognizes 486 */
case EM_486:
case EM_AMD64:
#else
case EM_X86_64:
#endif
return ("i386");
case EM_PPC:
case EM_PPC64:
return ("ppc");
default:
return ("other");
}
}
char *
{
switch (data) {
case ELFDATA2LSB:
return ("lsb");
case ELFDATA2MSB:
return ("msb");
default:
return ("unknown");
}
}
char *
{
switch (osabi) {
case ELFOSABI_NONE:
/* case ELFOSABI_SYSV: */
return ("none");
case ELFOSABI_LINUX:
return ("linux");
case ELFOSABI_SOLARIS:
return ("solaris");
default:
return ("other");
}
}
static char *
{
(void) PyErr_NoMemory();
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (id);
}
int
{
char *ident;
return (-1);
free(ident);
return (1);
}
free(ident);
return (0);
}
int
{
char *ident = NULL;
return (-1);
if (ident[EI_CLASS] == ELFCLASS32) {
free(ident);
return (1);
}
free(ident);
return (0);
}
static GElf_Ehdr *
{
if (!elf) {
"elf.so`gethead: argument 'elf' must not be NULL");
return (NULL);
}
(void) PyErr_NoMemory();
return (NULL);
}
return (NULL);
}
return (hdr);
}
{
(void) PyErr_NoMemory();
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (NULL);
}
return (hi);
}
/*
* For ELF nontriviality: Need to turn an ELF object into a unique hash.
*
* From Eric Saxe's investigations, we see that the following sections can
* generally be ignored:
*
* .SUNW_signature, .comment, .SUNW_dof, .debug, .plt, .rela.bss,
* .rela.plt, .line, .note
*
* Conversely, the following sections are generally significant:
*
*
* Accordingly, we will hash on the latter group of sections to determine our
* ELF hash.
*/
static int
{
return (0);
return (1);
}
typedef struct hashcb_data {
char *base;
/*
* Hashes a range from an mmap'd elf file
*/
static void
{
if (!size)
return;
}
}
}
/*
* getelfhash - gets SHA-1 hash of interesting portions of ELF file,
* where "interesting" is indicated by hashsection(). Returns NULL for
* failure or a pointer to the hash on success.
*/
static unsigned char *
{
goto bad;
}
goto bad;
}
goto bad;
}
if (hashsection(name)) {
/*
* We can't just push shdr.sh_size into
* SHA1Update(), as its raw bytes will be
* different on x86 than they are on sparc.
* Convert to network byte-order first.
*/
} else {
}
}
}
bad:
return (return_ptr);
}
/*
* getdynamic - returns a struct filled with the
* information we want from an ELF file. Returns NULL
* if it can't find everything (eg. not ELF file, wrong
* class of ELF file).
*/
{
/* Verneed */
int a = 0;
return (NULL);
}
goto bad;
}
goto bad;
}
/* get useful sections */
goto bad;
}
goto bad;
}
case SHT_DYNAMIC:
goto bad;
}
break;
#ifdef SHT_SUNW_verdef
case SHT_SUNW_verdef:
#else
case SHT_GNU_verdef:
#endif
goto bad;
}
break;
#ifdef SHT_SUNW_verneed
case SHT_SUNW_verneed:
#else
case SHT_GNU_verneed:
#endif
goto bad;
}
break;
}
}
/* Dynamic but no string table? */
"bad elf: didn't find the dynamic duo");
goto bad;
}
/* Parse dynamic section */
if (!(deps = liblist_alloc()))
goto bad;
for (t = 0; t < num_dyn; t++) {
goto bad;
}
case DT_NEEDED:
case DT_AUDIT:
case DT_DEPAUDIT:
case DT_FILTER:
case DT_SUNW_FILTER:
goto bad;
break;
case DT_RPATH:
break;
case DT_RUNPATH:
break;
case DT_POSFLAG_1:
t++;
}
}
}
/* Runpath supercedes rpath, but use rpath if no runpath */
if (!runpath)
/*
* Finally, get version information for each item in
* our dependency list. This part is a little messier,
* as it seems that libelf / gelf do not implement this.
*/
if (!(vers = liblist_alloc()))
goto bad;
if (vernum > 0 && data_verneed) {
}
for (t = 0; t < vernum; t++) {
if (ev)
if (!(veraux = liblist_alloc()))
goto bad;
if (ea)
goto bad;
}
}
goto bad;
}
}
/* Consolidate version and dependency information */
goto bad;
/*
* Now, figure out what versions we provide.
*/
if (!(verdef = liblist_alloc()))
goto bad;
if (verdefnum > 0 && data_verdef) {
}
for (t = 0; t < verdefnum; t++) {
if (vd)
if (va)
/* first one is name, rest are versions */
if (!def)
goto bad;
}
}
(void) PyErr_NoMemory();
goto bad;
}
return (dyn);
bad:
if (deps)
if (verdef)
if (vers)
if (elf)
return (NULL);
}
void
{
}
/*
* gethashes - returns a pointer to a struct filled with the hex
* digests of hashes computed from an ELF file.
*
* On error, will set Python error and return NULL.
*
* On success, the caller is responsible for freeing the returned
* buffer. For the following input parameters, that structure will
* contain:
*
* input : return structure member
* -------------------------------------------------------------------
* doelf > 0: generate hex digest of legacy SHA1 hash in .elfhash
*
* do256 > 0: generate hex digests of SHA-256 hashes of signed content
* in .hash_sha256 and unsigned content in .uhash_sha256
*
* do512 > 0: generate hex digests of SHA-512/256 hashes of signed
* content in .hash_sha512t_256 and unsigned content in
* .uhash_sha512t_256
*
* The SHA-256 and SHA-512/256 hex digest strings are each prefaced
* with strings describing how the content was extracted from the Elf
* object, and which hashing algorithm was used on that content:
*
* gelf:sha256:hexdigest
* gelf:sha512t_256:hexdigest
* gelf.unsigned:sha256:hexdigest
* gelf.unsigned:sha512t_256:hexdigest
*
* If any of the functions used to extract that data and generate
* these hashes changes, those prefixes must also be changed.
*/
{
return (NULL);
}
/*
* From here until the return value structure is allocated,
* all error returns should jump to hash_out.
*/
fd, 0)) == MAP_FAILED)) {
goto hash_out;
}
if (do256 > 0) {
(void) PyErr_NoMemory();
goto hash_out;
}
}
if (do512 > 0) {
(void) PyErr_NoMemory();
goto hash_out;
}
}
(void) PyErr_NoMemory();
goto hash_out;
}
/*
* From here, all error returns should jump to hash_error.
*/
if (doelf > 0) {
int i;
goto hash_error;
}
for (i = 0; i < 20; i++) {
}
*hp = '\0';
}
if (doelfrange > 0 &&
ELF_SR_SIGNED_INTERPRET, &hdata)) {
goto hash_error;
}
if (do256 > 0) {
int i;
for (i = 0; i < 32; i++) {
}
*hp = '\0';
}
if (do512 > 0) {
int i;
"gelf:sha512t_256:");
for (i = 0; i < 32; i++) {
}
*hp = '\0';
}
if (doelfrange > 0 &&
ELF_SR_INTERPRET, &hdata)) {
goto hash_error;
}
if (do256 > 0) {
int i;
"gelf.unsigned:sha256:");
for (i = 0; i < 32; i++) {
}
*hp = '\0';
}
if (do512 > 0) {
int i;
"gelf.unsigned:sha512t_256:");
for (i = 0; i < 32; i++) {
}
*hp = '\0';
}
return (hashes);
goto hash_out;
}