EDGESEC  0.1.0-alpha.0+sha.ca29a8277b72f80785649ea9ef9cd7edf642d939
Secure router - reference implementation
Data Structures | Macros | Functions
os.c File Reference
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <libgen.h>
#include <limits.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
#include <stdbool.h>
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <uuid/uuid.h>
#include "allocs.h"
#include "hashmap.h"
#include "log.h"
#include "os.h"
Include dependency graph for os.c:

Data Structures

struct  proc_signal_arg
 

Macros

#define MAX_64BIT_DIGITS   19
 

Functions

int become_daemon (int flags)
 Becomes a daemon. More...
 
bool is_number (const char *ptr)
 Check if a string is a number. More...
 
int8_t hex2num (char c)
 Hex char to number. More...
 
int edge_os_get_time (struct os_time *t)
 Get current time (sec, usec) in seconds since UNIX epoch. More...
 
int edge_os_get_reltime (struct os_reltime *t)
 Get relative time (sec, usec) More...
 
int edge_hexstr2bin (const char *hex, uint8_t *buf, size_t len)
 Convert ASCII hex string into binary data. More...
 
size_t edge_os_strlcpy (char *restrict dest, const char *restrict src, size_t siz)
 Copy a string with size bound and NUL-termination. More...
 
int edge_os_memcmp_const (const void *a, const void *b, size_t len)
 Constant time memory comparison. More...
 
int edge_os_get_random (unsigned char *buf, size_t len)
 Get cryptographically strong pseudo random data. More...
 
int os_get_random_int_range (int low, int up)
 Return a random int from a give range. More...
 
void os_init_random_seed (void)
 Initialises the random seed. More...
 
int os_get_random_number_s (unsigned char *buf, size_t len)
 Get a random number string. More...
 
void * __hide_aliasing_typecast (void *foo)
 
int read_command_output (int fd, process_callback_fn fn, void *ctx)
 
char ** copy_argv (const char *const argv[])
 Makes a copy of argv. More...
 
int run_command (char *const argv[], char *const envp[], process_callback_fn fn, void *ctx)
 Executes a command. More...
 
void log_run_command (const char *const argv[], int arg_count)
 Logs the given command. More...
 
int run_argv_command (const char *path, const char *const argv[], process_callback_fn fn, void *ctx)
 Executes a command with argument. More...
 
int fn_split_string_array (const char *str, size_t len, void *data)
 
ssize_t split_string (const char *str, char sep, split_string_fn fun, void *data)
 Splits a string into substrings (execute callback function) More...
 
ssize_t split_string_array (const char *str, char sep, UT_array *arr)
 Splits a string into substrings (save to array) More...
 
char * concat_paths (const char *path_left, const char *path_right)
 Concatenate two string paths. More...
 
char * get_valid_path (const char *path)
 Get the valid path string. More...
 
char * construct_path (const char *path_left, const char *path_right)
 Construct a valid path from two paths. More...
 
char * get_secure_path (const UT_array *bin_path_arr, const char *filename, bool real)
 Get the secure path string of a binary. More...
 
int is_proc_running (const char *name)
 Check if a process is running. More...
 
int list_dir (const char *dirpath, list_dir_fn fun, void *args)
 List the files in a directory. More...
 
pid_t is_proc_app (const char *path, const char *proc_name)
 Check if the given process's basename matches proc_name. More...
 
bool signal_dir_fn (char *path, void *args)
 
bool signal_process (const char *proc_name, int sig)
 Signal a process. More...
 
bool kill_process (char *proc_name)
 Kill a process by name. More...
 
char * string_array2string (const char *const strings[])
 Concatenates an array of strings into a single string. More...
 
int run_process (char *argv[], pid_t *child_pid)
 Executes a background process with an array of string arguments. More...
 
int make_file_exec_fd (int fd)
 Makes a file given by descriptor executable. More...
 
char * rtrim (char *str, const char *seps)
 Right trim the string. More...
 
void replace_string_char (char *s, char in, char out)
 Replace a character in a string with a given characater. More...
 
void os_to_timestamp (struct timeval ts, uint64_t *timestamp)
 get the timestamp in microseconds from struct timeval More...
 
int os_get_timestamp (uint64_t *timestamp)
 get the timestamp in microseconds from system time More...
 
void generate_radom_uuid (char rid[static MAX_RANDOM_UUID_LEN])
 Generates a random UUID string of MAX_RANDOM_UUID_LEN - 1 characters long not including '\0'. More...
 
size_t os_strnlen_s (const char *str, size_t max_len)
 Returns the size of string with a give max length. More...
 
bool find_dir_proc_fn (char *path, void *args)
 Callback function for list_dir function to check if process running. More...
 
int exist_dir (const char *dirpath)
 Check if folder exists. More...
 
int make_dirs_to_path (const char *file_path, mode_t mode)
 Recurisvely create directories to the given path. More...
 
int create_dir (const char *dirpath, mode_t mode)
 Creates a folder recursively. More...
 
int create_pipe_file (const char *path)
 Creates a FIFO pipe file. More...
 
int check_file_exists (const char *path, struct stat *sb)
 Check if a file exists. More...
 
int check_sock_file_exists (const char *path)
 Check if a socket file exists. More...
 
int get_hostname (char buf[static OS_HOST_NAME_MAX])
 Get the hostname of the running machine. More...
 
int lock_region (int fd, int type, int whence, int start, int len)
 
int lock_region_block (int fd, int type, int whence, int start, int len)
 
int create_pid_file (const char *pid_file, int flags)
 Open/create the file named in 'pidFile', lock it, optionally set the close-on-exec flag for the file descriptor, write our PID into the file, and (in case the caller is interested) return the file descriptor referring to the locked file. The caller is responsible for deleting 'pidFile' file (just) before process termination. 'progName' should be the name of the calling program (i.e., argv[0] or similar), and is used only for diagnostic messages. If we can't open 'pidFile', or we encounter some other error, then we print an appropriate diagnostic and terminate. More...
 
ssize_t read_file (const char *path, uint8_t **out)
 Read the entire file. More...
 
int read_file_string (const char *path, char **out)
 Read the entire file into a string. More...
 
ssize_t open_write_nonblock (const char *path, int *fd, const uint8_t *buffer, size_t length)
 Opens a file for writing and write a a buffer in nonblocking mode. More...
 
int get_commands_paths (const char *commands[], const UT_array *bin_path_arr, hmap_str_keychar **hmap_bin_paths)
 Returns the absolute path of system binaries. More...
 
char * string_append_char (const char *str, char character)
 Append a character to a string and return the new string. More...
 

Macro Definition Documentation

◆ MAX_64BIT_DIGITS

#define MAX_64BIT_DIGITS   19

Function Documentation

◆ __hide_aliasing_typecast()

void* __hide_aliasing_typecast ( void *  foo)

◆ become_daemon()

int become_daemon ( int  flags)

Becomes a daemon.

Parameters
flagsFlags fpor deamon settings
Returns
int 0 on success, -1 on failure

◆ check_file_exists()

int check_file_exists ( const char *  path,
struct stat *  sb 
)

Check if a file exists.

Parameters
[in]pathThe path to the file
[out]sbIf non-NULL, stores the stats of the file.
Returns
0 if it exists, -1 on failure

◆ check_sock_file_exists()

int check_sock_file_exists ( const char *  path)

Check if a socket file exists.

Parameters
pathThe path to the socket file
Returns
0 if it exists, -1 otherwise

◆ concat_paths()

char* concat_paths ( const char *  path_left,
const char *  path_right 
)

Concatenate two string paths.

Parameters
path_leftFirst string path
path_rightSecond string path
Returns
Concatenated paths. Please free() the return value when done.
Return values
NULLon memory allocation error.

◆ construct_path()

char* construct_path ( const char *  path_left,
const char *  path_right 
)

Construct a valid path from two paths.

Parameters
path_leftFirst path
path_rightSecond path
Returns
The output valid path. Please free() this string when done with it.
Return values
NULLon memory allocation error.

◆ copy_argv()

char** copy_argv ( const char *const  argv[])

Makes a copy of argv.

When writing code, we normally define argv using const char * string literals, e.g.: const char * args[] {"hello", "world", NULL};

However, the C functions (e.g. execve()) expect char * const *, aka the strings must be mallable (unsafe with string literals).

This function makes a copy of argv so that we don't get undefined behaviour by modifing const data.

The entire argv array (and strings) is allocated as a single malloc() so that you can use a single free() to release the memory when done.

Parameters
argvThe NULL-terminated array of '\0'-terminated strings to copy.
Returns
A modifiable copy of argv, or NULL if malloc() failed.
Postcondition
Use free() when finished with the argv_copy.

Array of strings.

The first part of the malloc-d data hold argv, which is an array of char *. The second part of the malloc-d data is a buffer containing all the string data (e.g. char).

E.g., for example, a copy of

const char* argv[] = {"Hello", "World!", NULL};

will look something like the following (for 64-bit ptrs):

Address 0-7 8-15 16-23 24-29 30-36
CType char* char* char* char[] char[]
Value 24 30 NULL "Hello" "World!"

Pointer to beginning of string buffer within argv_copy. This is a separate variable as it's a different type to copy_argv[0] (char vs char *), and therefore pointer arthmetic gets complicated.

◆ create_dir()

int create_dir ( const char *  dirpath,
mode_t  mode 
)

Creates a folder recursively.

If the parent folders do not exist, creates them too.

Parameters
[in]dirpathThe folder path
modeThe folder creation mode
Returns
0 on success, -1 on failure

◆ create_pid_file()

int create_pid_file ( const char *  pid_file,
int  flags 
)

Open/create the file named in 'pidFile', lock it, optionally set the close-on-exec flag for the file descriptor, write our PID into the file, and (in case the caller is interested) return the file descriptor referring to the locked file. The caller is responsible for deleting 'pidFile' file (just) before process termination. 'progName' should be the name of the calling program (i.e., argv[0] or similar), and is used only for diagnostic messages. If we can't open 'pidFile', or we encounter some other error, then we print an appropriate diagnostic and terminate.

Parameters
pid_fileThe pid file path to create
flagsThe pid file open flags
Returns
int The pif file descriptor, -1 on failure

◆ create_pipe_file()

int create_pipe_file ( const char *  path)

Creates a FIFO pipe file.

Parameters
[in]pathThe path to the pipe file
Returns
0 on success, -1 on failure

◆ edge_hexstr2bin()

int edge_hexstr2bin ( const char *  hex,
uint8_t *  buf,
size_t  len 
)

Convert ASCII hex string into binary data.

Parameters
hexASCII hex string (e.g., "01ab")
bufBuffer for the binary data
lenLength of the text to convert in bytes (of buf); hex will be double this size
Returns
int 0 on success, -1 on failure (invalid hex string)

◆ edge_os_get_random()

int edge_os_get_random ( unsigned char *  buf,
size_t  len 
)

Get cryptographically strong pseudo random data.

Parameters
bufBuffer for pseudo random data.
lenLength of the buffer.
Returns
int 0 on success, -1 on failure

◆ edge_os_get_reltime()

int edge_os_get_reltime ( struct os_reltime t)

Get relative time (sec, usec)

Unlike edge_os_get_time(), the time from this function will never go backwards (e.g. due to NTP).

Parameters
[out]tPointer to buffer for the time. If there is a failure, may write invalid data.
Returns
int 0 on success, -1 on failure

◆ edge_os_get_time()

int edge_os_get_time ( struct os_time t)

Get current time (sec, usec) in seconds since UNIX epoch.

Parameters
[out]tPointer to buffer for the time If there is a failure, may write invalid data.
Returns
int 0 on success, -1 on failure

◆ edge_os_memcmp_const()

int edge_os_memcmp_const ( const void *  a,
const void *  b,
size_t  len 
)

Constant time memory comparison.

This function is meant for comparing passwords or hash values where difference in execution time could provide external observer information about the location of the difference in the memory buffers. The return value does not behave like os_memcmp(), i.e., edge_os_memcmp_const() cannot be used to sort items into a defined order. Unlike os_memcmp(), execution time of edge_os_memcmp_const() does not depend on the contents of the compared memory buffers, but only on the total compared length.

Parameters
aFirst buffer to compare
bSecond buffer to compare
lenNumber of octets to compare
Returns
int 0 if buffers are equal, non-zero if not

◆ edge_os_strlcpy()

size_t edge_os_strlcpy ( char *restrict  dest,
const char *restrict  src,
size_t  siz 
)

Copy a string with size bound and NUL-termination.

This function matches in behavior with the strlcpy(3) function in OpenBSD.

Parameters
destDestination string
srcSource string
sizSize of the target buffer
Returns
size_t Total length of the target string (length of src) (not including NUL-termination)

◆ exist_dir()

int exist_dir ( const char *  dirpath)

Check if folder exists.

Parameters
dirpathThe folder path
Returns
int 1 if exists, 0 otherwise, -1 on failure

◆ find_dir_proc_fn()

bool find_dir_proc_fn ( char *  path,
void *  args 
)

Callback function for list_dir function to check if process running.

Parameters
[in]pathThe process path
[in,out]argsThe callback arguments of type struct find_dir_type
Returns
bool true if process running, false otherwise

◆ fn_split_string_array()

int fn_split_string_array ( const char *  str,
size_t  len,
void *  data 
)

◆ generate_radom_uuid()

void generate_radom_uuid ( char  rid[static MAX_RANDOM_UUID_LEN])

Generates a random UUID string of MAX_RANDOM_UUID_LEN - 1 characters long not including '\0'.

Parameters
[out]ridThe output string of MAX_RANDOM_UUID_LEN bytes

◆ get_commands_paths()

int get_commands_paths ( const char *  commands[],
const UT_array *  bin_path_arr,
hmap_str_keychar **  hmap_bin_paths 
)

Returns the absolute path of system binaries.

Parameters
[in]commandsArray of system binaries name strings. The last entry must be a NULL ptr.
[in]bin_path_arrArray of system binaries default search paths
[out]hmap_bin_pathsThe created map of system binary to absolute path.
Returns
int 0 on success, -1 on failure

◆ get_hostname()

int get_hostname ( char  buf[static OS_HOST_NAME_MAX])

Get the hostname of the running machine.

Parameters
[out]bufBuffer to store the returned hostname. Must be at least OS_HOST_NAME_MAX bytes long. Warning, this string might not be NULL-terminated if it's exactly OS_HOST_NAME_MAX bytes long.
Returns
int 0 on success, -1 on failure

◆ get_secure_path()

char* get_secure_path ( const UT_array *  bin_path_arr,
const char *  filename,
bool  real 
)

Get the secure path string of a binary.

Parameters
bin_path_arrThe path string of binary
filenameThe binary name
realtrue to return the real link
Returns
The secure path, or NULL on error. Must be freed with os_free().

◆ get_valid_path()

char* get_valid_path ( const char *  path)

Get the valid path string.

Parameters
pathInput string path
Returns
Output valid path. Please free() this string when done with it.
Return values
NULLon memory allocation error.

◆ hex2num()

int8_t hex2num ( char  c)

Hex char to number.

// returns 0x9 aka 9 aka '\x09'
hex2num('9')
int8_t hex2num(char c)
Hex char to number.
Definition: os.c:138
Parameters
[in]cHex char
Returns
Converted byte from 0-15, or -1 on error.

◆ is_number()

bool is_number ( const char *  ptr)

Check if a string is a number.

Parameters
ptrString pointer
Returns
true if numer, false otherwise

◆ is_proc_app()

pid_t is_proc_app ( const char *  path,
const char *  proc_name 
)

Check if the given process's basename matches proc_name.

Checks both:

  • the realpath (aka /proc/[pid]/exe), and
  • the given argv0 (from /proc/[pid]/cmdline).

As an example, if a process was started with /usr/bin/gcc, which is a symlink to /usr/bin/x86_64-linux-gnu-gcc-11, then bothis_proc_app(..., "gcc") AND is_proc_app(..., "x86_64-linux-gnu-gcc-11") will work.

Parameters
pathThe /proc/[pid] folder for the process
proc_nameThe process name to search for.
Returns
The process PID if the process's basename contains the given proc_name string, or 0 if it doesn't.

◆ is_proc_running()

int is_proc_running ( const char *  name)

Check if a process is running.

Parameters
nameThe process name
Returns
int 1 if running, 0 otherwise, -1 on failure

◆ kill_process()

bool kill_process ( char *  proc_name)

Kill a process by name.

Parameters
proc_nameThe process name
Returns
bool true on success, false otherwise

◆ list_dir()

int list_dir ( const char *  dirpath,
list_dir_fn  fun,
void *  args 
)

List the files in a directory.

Parameters
dirpathThe directory path
funThe callback function If this function ever returns false, list_dir will return -1.
argsThe callback function arguments
Return values
0On success
-1On error

◆ lock_region()

int lock_region ( int  fd,
int  type,
int  whence,
int  start,
int  len 
)

◆ lock_region_block()

int lock_region_block ( int  fd,
int  type,
int  whence,
int  start,
int  len 
)

◆ log_run_command()

void log_run_command ( const char *const  argv[],
int  arg_count 
)

Logs the given command.

Parameters
argvArray of command parameters.
arg_countLength of array (not including NULL terminator).

◆ make_dirs_to_path()

int make_dirs_to_path ( const char *  file_path,
mode_t  mode 
)

Recurisvely create directories to the given path.

Creates the directories recursively to the given path.

Does NOT create the final file, use create_dir() if you want if you want to create the entire path as dirs.

Example:

// will create the directories /var/run/exampledir/
make_dirs_to_path("/var/run/exampledir/example.pid", 0755);
int make_dirs_to_path(const char *file_path, mode_t mode)
Recurisvely create directories to the given path.
Definition: os.c:1197
Parameters
[in]file_pathThe directories to create to the path.
modeThe folder create mode.
Returns
0 on success, -1 on failure.
See also
Original source-code used under fair-use from https://stackoverflow.com/a/9210960

◆ make_file_exec_fd()

int make_file_exec_fd ( int  fd)

Makes a file given by descriptor executable.

Parameters
fdFile descriptor
Returns
int 0 on succes, -1 on error

◆ open_write_nonblock()

ssize_t open_write_nonblock ( const char *  path,
int *  fd,
const uint8_t *  buffer,
size_t  length 
)

Opens a file for writing and write a a buffer in nonblocking mode.

Parameters
path[in]The file path
fd[in,out]The file descriptor. If this is non-0, opens the file given by path, and sets fd to the new file descriptor. Otherwise, path is ignored, and fd is used. Please close the created fd when done with it.
buffer[in]The buffer to write
length[in]The size of the buffer
Returns
number of bytes written, -1 on failure

◆ os_get_random_int_range()

int os_get_random_int_range ( int  low,
int  up 
)

Return a random int from a give range.

Parameters
lowThe range lower bound
upThe range upper bound
Returns
int The returned random int

◆ os_get_random_number_s()

int os_get_random_number_s ( unsigned char *  buf,
size_t  len 
)

Get a random number string.

Parameters
bufBuffer for the random string.
lenLength of the buffer.
Returns
int 0 on success, -1 on failure

◆ os_get_timestamp()

int os_get_timestamp ( uint64_t *  timestamp)

get the timestamp in microseconds from system time

Parameters
[out]timestampThe returned timestamp
Returns
int 0 on success, -1 on failure

◆ os_init_random_seed()

void os_init_random_seed ( void  )

Initialises the random seed.

◆ os_strnlen_s()

size_t os_strnlen_s ( const char *  str,
size_t  max_len 
)

Returns the size of string with a give max length.

Parameters
[in]strThe string pointer
max_lenThe string max length
Returns
Total length of the string, or max_len if the string is longer than max_len.

◆ os_to_timestamp()

void os_to_timestamp ( struct timeval  ts,
uint64_t *  timestamp 
)

get the timestamp in microseconds from struct timeval

Parameters
[in]tsThe input struct timeval
[out]timestampThe returned timestamp

◆ read_command_output()

int read_command_output ( int  fd,
process_callback_fn  fn,
void *  ctx 
)

◆ read_file()

ssize_t read_file ( const char *  path,
uint8_t **  out 
)

Read the entire file.

Parameters
pathThe file path
[out]outPointer to the output buffer, or NULL on error. Will be malloc()-ed, so you must free() this when done.
Returns
ssize_t The file size, -1 on failure

◆ read_file_string()

int read_file_string ( const char *  path,
char **  out 
)

Read the entire file into a string.

Parameters
[in]pathThe file path
[out]outThe pointer to the output string. You must free() this variable if read_file_string() is successful.
Returns
0 on success, -1 on failure

◆ replace_string_char()

void replace_string_char ( char *  s,
char  in,
char  out 
)

Replace a character in a string with a given characater.

Parameters
sThe input string
inThe character to be replaced
outThe character to replace with

◆ rtrim()

char* rtrim ( char *  str,
const char *  seps 
)

Right trim the string.

Parameters
strThe source string
sepsThe separator string, if NULL then the separator used is "\t\n\v\f\r "
Returns
char* The pointer to the source string

◆ run_argv_command()

int run_argv_command ( const char *  path,
const char *const  argv[],
process_callback_fn  fn,
void *  ctx 
)

Executes a command with argument.

Parameters
pathThe command path
argvThe command arguments without the process path
fnCallback function
ctxThe callback function context
Return values
-1Returns -1 on error.
0Returns 0 on success.

◆ run_command()

int run_command ( char *const  argv[],
char *const  envp[],
process_callback_fn  fn,
void *  ctx 
)

Executes a command.

Parameters
argvThe command arguments including the process path
envpThe environment variables
fnCallback function
ctxThe callback function context
Returns
int excve status code

◆ run_process()

int run_process ( char *  argv[],
pid_t *  child_pid 
)

Executes a background process with an array of string arguments.

Parameters
[in]argvThe array of string arguments terminated with NULL and the first argument is the absolute path of the process.
[out]child_pidThe returned child pid
Return values
0The child process has been created, and is either:
  • still running, OR
  • exited with exit code 0
-1Error, please see errno for more details.
1-255The child process has exited, and the return value is this non-zero/error exit code.

◆ signal_dir_fn()

bool signal_dir_fn ( char *  path,
void *  args 
)

◆ signal_process()

bool signal_process ( const char *  proc_name,
int  sig 
)

Signal a process.

Parameters
[in]proc_nameThe process name
sigThe signal value
Returns
true on success, false on failure

◆ split_string()

ssize_t split_string ( const char *  str,
char  sep,
split_string_fn  fun,
void *  data 
)

Splits a string into substrings (execute callback function)

Parameters
strString to split
sepString separator
funCallback function
dataParam for callback function
Returns
ssize_t number of stubstrings

◆ split_string_array()

ssize_t split_string_array ( const char *  str,
char  sep,
UT_array *  arr 
)

Splits a string into substrings (save to array)

Parameters
strString to split
sepString separator
arrArray to save the substrings
Returns
ssize_t number of stubstrings

◆ string_append_char()

char* string_append_char ( const char *  str,
char  character 
)

Append a character to a string and return the new string.

The returned pointer must be passed to free() to avoid a memory leak.

Parameters
[in]strThe string to append to
characterThe character to append
Returns
The appended string on success, NULL on failure

◆ string_array2string()

char* string_array2string ( const char *const  strings[])

Concatenates an array of strings into a single string.

Parameters
stringsThe array of string, the last element is NULL
Returns
The concatenated string, which must be free()-ed when done, or NULL on error.