Skip to content

Instantly share code, notes, and snippets.

@tin-z
Last active November 9, 2023 22:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tin-z/17292073289c0451b72e1108d20a2116 to your computer and use it in GitHub Desktop.
Save tin-z/17292073289c0451b72e1108d20a2116 to your computer and use it in GitHub Desktop.
Notes about C lib functions on Linux

file i/o

fcntl

  • performing operations on an open file descriptor
#include <fcntl.h>
int fcntl(int fd, int cmd, ...);

pread

  • read #count bytes from fd open file descriptor starting at offset offset (the file offset is unchanged)
ssize_t pread(int fd, void *buf, size_t count, off_t offset);

pwrite

  • write #count bytes into fd open file descriptor starting at offset offset (the file offset is unchanged)
ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

readv

  • read from fd file descriptor and save the output splited onto iov structures. iovcnt is the number of iov structs
ssize_t readv(int fd, const struct iovec *iov, int iovcnt);

writev

  • write to fd file descriptor the input gathered from iov structs
ssize_t writev(int fd, const struct iovec *iov, int iovcnt);

truncate

  • open pathname file with read-write permissions and set its size to length
int truncate(const char *pathname, off_t length);

ftruncate

  • Set the fd readable-writable file descriptor size to length
int ftruncate(int fd, off_t length);

mkstemp

  • Create a file below "/tmp" folder with read and write permissions and make sure does not exists by giving also the flag O_EXCL. template argument is used as prefix for the filename, then a randomic-generated number is appended.
int mkstemp(char *template);

inotify

  • inotify - monitoring filesystem events
int inotify_init(void);
int inotify_add_watch(int wd, const char *pathname, uint32_t mask);
int inotify_rm_watch(int fd, int wd);

int wd = inotify_init();
int fw = inotify_add_watch(wd, "/etc/passwd", IN_ACCESS | IN_MODIFY | IN_ATTRIB);
...


memory allocation

memalign

  • Allocate memory of bytes size with an address aligned to a multiple of boundary
void *memalign(size_t boundary, size_t size);

alloca

  • allocate memory on the stack
void *alloca(size_t size);


password management

getpwnam

  • get name user entry on the /etc/shadow file as passwd struct
struct passwd *getpwnam(const char *name);

getgrnam

  • get name group entry on the /etc/group file as group struct
struct group *getgrnam(const char *name);

lckpwdf

  • lock shadow file access.
int lckpwdf(void);

ulckpwdf

  • unlock shadow file (note there's no protection against direct access to the shadow file, only programs using lckpwdf will notice the lock)
int ulckpwdf(void);

getspent

  • return a pointer to the next entry on the shadow password database as spwd struct
struct spwd *getspent(void);


POSIX message queue (mqueue)

mq_open

  • open an existing mqueue or create it based on oflag and mode arguments. If oflag specifies O_CREAT, then mode and attr arguments are required also
#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <mqueue.h>

mqd_t mq_open(const char *name, int oflag);
mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr);

mq_send

  • send msg_ptr to mqdes mqueue, etc.
int mq_send(mqd_t mqdes, const char *msg_ptr, size_t msg_len, unsigned int msg_prio);

mq_receive

  • receive data from mqdes mqueue and store to msg_ptr buffer
ssize_t mq_receive(mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned int *msg_prio);

mq_close

  • close a message queue descriptor
int mq_close(mqd_t mqdes);

mq_unlink

  • remove the specified mqueue. The queue itself is destroyed after any other process does not use it anymore
int mq_unlink(const char *name);


Shared memory

ftok

  • convert pathname and a project identifier to a System V IPC key

    • return value then can be used with msgget(2), semget(2), or shmget(2)
key_t ftok(const char *pathname, int proj_id);

shmget

  • allocates a System V shared memory segment using key and shmflg as permissions

    • shmflg does use macros defined on 'bits/ipc.h', 'bits/shm.h' and 'linux/stat.h' files
int shmget(key_t key, size_t size, int shmflg);


Control flow

setjmp/longjmp

  • "nonlocal gotos"
  • A jmp point is defined by calling int setjmp(jmp_buf env)
  • To return to that point longjmp(jmp_buf env, int val); is called, with env being the same one defined before and val the return value with 0 as the success state
  • After calling longjmp registers and stack pointer are restored to the state they were before on setjmp call
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);


Process

posix_spawn

  • The posix_spawn() and posix_spawnp() functions are used to create a new child process that executes a specified file. These functions were specified by POSIX to provide a standardized method of creating new processes on machines that lack the capability to support the fork(2) system call. These machines are generally small, embedded systems lacking MMU support.
  • The posix_spawn() and posix_spawnp() functions provide the functionality of a combined fork(2) and exec(3), with some optional housekeeping steps in the child process before the exec(3). These functions are not meant to replace the fork(2) and execve(2) system calls. In fact, they provide only a subset of the functionality that can be achieved by using the system calls.
       #include <spawn.h>

       int posix_spawn(pid_t *restrict pid, const char *restrict path,
                       const posix_spawn_file_actions_t *restrict file_actions,
                       const posix_spawnattr_t *restrict attrp,
                       char *const argv[restrict],
                       char *const envp[restrict]);


Other

unshare

  • disassociate parts of the process execution context (e.g. mount namespace, shared memory) run program in new name namespaces
int unshare(int flags);

getcontext, setcontext

  • get or set the user context. Thus permitting to perform a non-local jump from one context to another. Useful for ROP
int getcontext(ucontext_t *ucp);
int setcontext(const ucontext_t *ucp);


Security caveats

  • snprintf(), vsnprintf() does NULL terminating the dst buffer and does return the number of characters which would have been written if enough space had been available.

  • strncpy(), stpncpy() does not NULL terminating the dst buffer if len(src) > len(dst)

  • strncat() the size argument should indicate the amount of space left in the dst buffer and not the total space in dst

  • strlcpy() does return src buffer length

  • strlcat() does return src buffer length, also the size argument indicates the total space in dst


From here chatgpt output:

  • tmpnam(), tempnam(), mktemp() are vulnerable to race conditions in a multithreaded env

  • The alloca() function, which allocates memory on the stack, can be prone to stack-based buffer overflows if it is used incorrectly.

  • The memchr() function, which searches for a specific character in a memory block, can be prone to timing attacks if it is used to search for sensitive data.

  • The memccpy function, which copies bytes from one memory block to another until a specific character is encountered, can be prone to buffer overflows if it is used incorrectly.

  • The memmem function, which searches for a specific pattern in a memory block, can be prone to buffer overflows if it is used incorrectly.

  • The msync function, which synchronizes a memory mapping with a file, can be prone to privilege escalation if it is used incorrectly.

  • The mremap function, which changes the size of a memory mapping, can be prone to privilege escalation if it is used incorrectly.

  • The madvise function, which advises the kernel on the use of a memory region, can be prone to privilege escalation if it is used incorrectly.

  • The mlock function, which locks a memory region in physical memory, can be prone to privilege escalation if it is used incorrectly.

  • The mlockall function, which locks all currently mapped memory pages in physical memory, can be prone to privilege escalation if it is used incorrectly.

  • The posix_memalign function, which allocates memory according to specified alignment constraints, can be prone to heap-based buffer overflows if it is used incorrectly.

  • The valloc function, which allocates memory on a page boundary, can be prone to heap-based buffer overflows if it is used incorrectly.



ref

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment