Skip to content

Commit 67b6bbe

Browse files
committed
fix #27, expose less symbols from libear
1 parent bd0b745 commit 67b6bbe

File tree

8 files changed

+253
-323
lines changed

8 files changed

+253
-323
lines changed

libear/execs.c renamed to libear/ear.c

Lines changed: 250 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,48 +5,85 @@
55
// License. See LICENSE.TXT for details.
66
*/
77

8-
#include "config.h"
8+
/**
9+
This file implements a shared library. This library can be pre-loaded by
10+
the dynamic linker of the Operating System (OS). It implements a few function
11+
related to process creation. By pre-load this library the executed process
12+
uses these functions instead of those from the standard library.
13+
14+
The idea here is to inject a logic before call the real methods. The logic is
15+
to dump the call into a file. To call the real method this library is doing
16+
the job of the dynamic linker.
17+
18+
The only input for the log writing is about the destination directory.
19+
This is passed as environment variable.
20+
*/
921

10-
#include "stringarray.h"
11-
#include "environ.h"
12-
#include "protocol.h"
22+
#include "config.h"
1323

1424
#include <sys/types.h>
1525
#include <sys/stat.h>
26+
#include <ctype.h>
27+
#include <stddef.h>
1628
#include <stdarg.h>
1729
#include <stdlib.h>
1830
#include <stdio.h>
31+
#include <string.h>
1932
#include <unistd.h>
20-
33+
#include <fcntl.h>
2134
#include <dlfcn.h>
2235

2336
#if defined HAVE_POSIX_SPAWN || defined HAVE_POSIX_SPAWNP
2437
#include <spawn.h>
2538
#endif
2639

40+
#ifdef HAVE_NSGETENVIRON
41+
#include <crt_externs.h>
42+
#else
43+
extern char **environ;
44+
#endif
2745

2846
#ifdef __APPLE__
2947
# define EXEC_LOOP_ON_EXECVE
3048
#endif
3149

32-
static char const * * update_environment(char * const envp[]);
3350

34-
static void report_call(char const * fun, char const * const argv[]);
51+
typedef struct
52+
{
53+
pid_t pid;
54+
pid_t ppid;
55+
char const * fun;
56+
char const * cwd;
57+
char const * * cmd;
58+
} bear_message_t;
59+
60+
static char const * * bear_update_environment(char * const envp[]);
61+
static void bear_report_call(char const * fun, char const * const argv[]);
62+
static void bear_write_message(int fd, bear_message_t const * e);
63+
static void bear_send_message(char const * destination, bear_message_t const * e);
64+
static char const * * bear_update_environ(char const * * in, char const * key);
65+
static char * * bear_get_environ(void);
66+
static char const ** bear_strings_build(char const * arg, va_list *ap);
67+
static char const ** bear_strings_copy(char const ** const in);
68+
static char const ** bear_strings_append(char const ** in, char const * e);
69+
static size_t bear_strings_length(char const * const * in);
70+
static void bear_strings_release(char const **);
71+
3572

3673
#ifdef EXEC_LOOP_ON_EXECVE
3774
static int already_reported = 0;
3875
# define REPORT_CALL(ARGV_) \
3976
int const report_state = already_reported; \
4077
if (!already_reported) { \
41-
report_call(__func__, (char const * const *)ARGV_); \
78+
bear_report_call(__func__, (char const * const *)ARGV_); \
4279
already_reported = 1; \
4380
}
4481
# define REPORT_FAILED_CALL(RESULT_) \
4582
if (!report_state) { \
4683
already_reported = 0; \
4784
}
4885
#else
49-
# define REPORT_CALL(ARGV_) report_call(__func__, (char const * const *)ARGV_);
86+
# define REPORT_CALL(ARGV_) bear_report_call(__func__, (char const * const *)ARGV_);
5087
# define REPORT_FAILED_CALL(RESULT_)
5188
#endif
5289

@@ -90,6 +127,9 @@ static int call_posix_spawnp(pid_t *restrict pid,
90127
#endif
91128

92129

130+
/* These are the methods we are try to hijack.
131+
*/
132+
93133
#if defined HAVE_VFORK && defined EXEC_LOOP_ON_EXECVE
94134
pid_t vfork(void)
95135
{
@@ -249,14 +289,16 @@ int posix_spawnp(pid_t *restrict pid,
249289
}
250290
#endif
251291

292+
/* These are the methods which forward the call to the standard implementation. */
293+
252294
#ifdef HAVE_EXECVE
253295
static int call_execve(const char * path, char * const argv[], char * const envp[])
254296
{
255297
typedef int (*func)(const char *, char * const *, char * const *);
256298

257299
DLSYM(func, fp, "execve");
258300

259-
char const ** const menvp = update_environment(envp);
301+
char const ** const menvp = bear_update_environment(envp);
260302
int const result = (*fp)(path, argv, (char * const *)menvp);
261303
bear_strings_release(menvp);
262304
return result;
@@ -270,7 +312,7 @@ static int call_execvpe(const char * file, char * const argv[], char * const env
270312

271313
DLSYM(func, fp, "execvpe");
272314

273-
char const ** const menvp = update_environment(envp);
315+
char const ** const menvp = bear_update_environment(envp);
274316
int const result = (*fp)(file, argv, (char * const *)menvp);
275317
bear_strings_release(menvp);
276318
return result;
@@ -341,7 +383,73 @@ static int call_posix_spawnp(pid_t *restrict pid,
341383
}
342384
#endif
343385

344-
static char const * * update_environment(char * const envp[])
386+
/* these methods are for to write log about the process creation. */
387+
388+
static void bear_report_call(char const * fun, char const * const argv[])
389+
{
390+
char * const destination = getenv(ENV_OUTPUT);
391+
if (0 == destination)
392+
{
393+
perror("bear: getenv");
394+
exit(EXIT_FAILURE);
395+
}
396+
const char * cwd = getcwd(NULL, 0);
397+
if (0 == cwd)
398+
{
399+
perror("bear: getcwd");
400+
exit(EXIT_FAILURE);
401+
}
402+
403+
bear_message_t const msg =
404+
{
405+
getpid(),
406+
getppid(),
407+
fun,
408+
cwd,
409+
(char const **)argv
410+
};
411+
bear_send_message(destination, &msg);
412+
413+
free((void *)cwd);
414+
}
415+
416+
static void bear_write_message(int fd, bear_message_t const * e)
417+
{
418+
static int const RS = 0x1e;
419+
static int const US = 0x1f;
420+
dprintf(fd, "%d%c", e->pid, RS);
421+
dprintf(fd, "%d%c", e->ppid, RS);
422+
dprintf(fd, "%s%c", e->fun, RS);
423+
dprintf(fd, "%s%c", e->cwd, RS);
424+
size_t const length = bear_strings_length(e->cmd);
425+
for (size_t it = 0; it < length; ++it)
426+
{
427+
dprintf(fd, "%s%c", e->cmd[it], US);
428+
}
429+
}
430+
431+
static void bear_send_message(char const * destination, bear_message_t const * msg)
432+
{
433+
char * filename = 0;
434+
if (-1 == asprintf(&filename, "%s/cmd.XXXXXX", destination))
435+
{
436+
perror("bear: asprintf");
437+
exit(EXIT_FAILURE);
438+
}
439+
int fd = mkstemp(filename);
440+
free((void *)filename);
441+
if (-1 == fd)
442+
{
443+
perror("bear: open");
444+
exit(EXIT_FAILURE);
445+
}
446+
bear_write_message(fd, msg);
447+
close(fd);
448+
}
449+
450+
/* update environment assure that chilren processes will copy the desired behaviour */
451+
452+
static char const * * bear_update_environment(char * const envp[])
345453
{
346454
char const ** result = bear_strings_copy((char const * *)envp);
347455
result = bear_update_environ(result, ENV_PRELOAD);
@@ -352,30 +460,144 @@ static char const * * update_environment(char * const envp[])
352460
return result;
353461
}
354462

355-
typedef void (*send_message)(char const * destination, bear_message_t const *);
463+
static char const * * bear_update_environ(char const * envs[], char const * key)
464+
{
465+
char const * const value = getenv(key);
466+
if (0 == value)
467+
{
468+
perror("bear: getenv");
469+
exit(EXIT_FAILURE);
470+
}
471+
// find the key if it's there
472+
size_t const key_length = strlen(key);
473+
char const * * it = envs;
474+
for (; (it) && (*it); ++it)
475+
{
476+
if ((0 == strncmp(*it, key, key_length)) &&
477+
(strlen(*it) > key_length) &&
478+
('=' == (*it)[key_length]))
479+
break;
480+
}
481+
// check the value might already correct
482+
char const * * result = envs;
483+
if ((0 != it) && ((0 == *it) || (strcmp(*it + key_length + 1, value))))
484+
{
485+
char * env = 0;
486+
if (-1 == asprintf(&env, "%s=%s", key, value))
487+
{
488+
perror("bear: asprintf");
489+
exit(EXIT_FAILURE);
490+
}
491+
if (*it)
492+
{
493+
free((void *)*it);
494+
*it = env;
495+
}
496+
else
497+
result = bear_strings_append(envs, env);
498+
}
499+
return result;
500+
}
501+
502+
static char * * bear_get_environ(void)
503+
{
504+
#ifdef HAVE_NSGETENVIRON
505+
// environ is not available for shared libraries have to use _NSGetEnviron()
506+
return *_NSGetEnviron();
507+
#else
508+
return environ;
509+
#endif
510+
}
356511

357-
static void report(send_message fp, char const * destination, char const * fun, char const * const argv[])
512+
/* util methods to deal with string arrays. environment and process arguments
513+
are both represented as string arrays. */
514+
515+
static char const ** bear_strings_build(char const * const arg, va_list *args)
358516
{
359-
bear_message_t const msg =
517+
char const ** result = 0;
518+
size_t size = 0;
519+
for (char const * it = arg; it; it = va_arg(*args, char const *))
360520
{
361-
getpid(),
362-
getppid(),
363-
fun,
364-
getcwd(NULL, 0),
365-
(char const **)argv
366-
};
367-
(*fp)(destination, &msg);
368-
free((void *)msg.cwd);
521+
result = realloc(result, (size + 1) * sizeof(char const *));
522+
if (0 == result)
523+
{
524+
perror("bear: realloc");
525+
exit(EXIT_FAILURE);
526+
}
527+
char const * copy = strdup(it);
528+
if (0 == copy)
529+
{
530+
perror("bear: strdup");
531+
exit(EXIT_FAILURE);
532+
}
533+
result[size++] = copy;
534+
}
535+
result = realloc(result, (size + 1) * sizeof(char const *));
536+
if (0 == result)
537+
{
538+
perror("bear: realloc");
539+
exit(EXIT_FAILURE);
540+
}
541+
result[size++] = 0;
542+
543+
return result;
369544
}
370545

371-
static void report_call(char const * fun, char const * const argv[])
546+
static char const ** bear_strings_copy(char const ** const in)
372547
{
373-
char * const destination = getenv(ENV_OUTPUT);
374-
if (0 == destination)
548+
size_t const size = bear_strings_length(in);
549+
550+
char const ** const result = malloc((size + 1) * sizeof(char const *));
551+
if (0 == result)
375552
{
376-
perror("bear: getenv");
553+
perror("bear: malloc");
377554
exit(EXIT_FAILURE);
378555
}
379556

380-
report(bear_send_message, destination, fun, argv);
557+
char const ** out_it = result;
558+
for (char const * const * in_it = in; (in_it) && (*in_it); ++in_it, ++out_it)
559+
{
560+
*out_it = strdup(*in_it);
561+
if (0 == *out_it)
562+
{
563+
perror("bear: strdup");
564+
exit(EXIT_FAILURE);
565+
}
566+
}
567+
*out_it = 0;
568+
return result;
569+
}
570+
571+
static char const ** bear_strings_append(char const ** const in, char const * const e)
572+
{
573+
if (0 == e)
574+
return in;
575+
576+
size_t size = bear_strings_length(in);
577+
char const ** result = realloc(in, (size + 2) * sizeof(char const *));
578+
if (0 == result)
579+
{
580+
perror("bear: realloc");
581+
exit(EXIT_FAILURE);
582+
}
583+
result[size++] = e;
584+
result[size++] = 0;
585+
return result;
586+
}
587+
588+
static size_t bear_strings_length(char const * const * const in)
589+
{
590+
size_t result = 0;
591+
for (char const * const * it = in; (it) && (*it); ++it)
592+
++result;
593+
return result;
594+
}
595+
596+
static void bear_strings_release(char const ** in)
597+
{
598+
for (char const * const * it = in; (it) && (*it); ++it)
599+
{
600+
free((void *)*it);
601+
}
602+
free((void *)in);
381603
}

0 commit comments

Comments
 (0)