intercepting the openat() system call for GNU tar - gcc

I'm trying to intercept the openat() system call on Linux using a custom shared library that I can load via LD_PRELOAD. An example intercept-openat.c has this content:
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <dlfcn.h>
int (*_original_openat)(int dirfd, const char *pathname, int flags, mode_t mode);
void init(void) __attribute__((constructor));
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
void init(void)
{
_original_openat = (int (*)(int, const char *, int, mode_t))
dlsym(RTLD_NEXT, "openat");
}
int openat(int dirfd, const char *pathname, int flags, mode_t mode)
{
fprintf(stderr, "intercepting openat()...\n");
return _original_openat(dirfd, pathname, flags, mode);
}
I compile it via gcc -fPIC -Wall -shared -o intercept-openat.so intercept-openat.c -ldl. Then, when I run this small example program:
int main(int argc, char *argv[])
{
int fd;
fd = openat(AT_FDCWD, "/home/feh/.vimrc", O_RDONLY);
if(fd == -1)
return -1;
close(fd);
return 0;
}
The openat() call is re-written via the library:
$ LD_PRELOAD=./intercept-openat.so ./openat
intercepting openat()...
However, the same does not happen with GNU tar, even though it uses the same system call:
$ strace -e openat tar cf /tmp/t.tgz .vimrc
openat(AT_FDCWD, ".vimrc", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_NOFOLLOW|O_CLOEXEC) = 4
$ LD_PRELOAD=./intercept-openat.so tar cf /tmp/t.tgz .vimrc
So the custom openat() from intercept-openat.so is not being called. Why is that?

It uses the same system call, but apparently it does not call that via the same C function. Alternatively, it could be that it does, but it's statically linked.
Either way, I think you've proved that it never dynamically links a function names "openat". If you still want to pursue this option, you might like to see if it links against a specific version of that function, but that's a long shot.
You can still intercept the system call by writing your program to use ptrace. This is the same interface used by strace and gdb. It will have a higher performance penalty though.
http://linux.die.net/man/2/ptrace

Related

Program segment fault around std::pmr::synchronized_pool_resource

The program does nothing except farewell to the world:
/* Ubuntu 18.04 with GCC 10.1.0 and libstdc++-10-dev */
#include <memory_resource>
#include <concepts>
#include <ranges>
#include <string_view>
/* declare global memory resource */
std::pmr::synchronized_pool_resource pool;
int main(int argv, char * argc[]){
std::puts("Goodbye World!");
}
It compiles fine, but terminates with SEGV on
/usr/include/c++/10/memory_resource
line 445, in constructor of SPR:
synchronized_pool_resource()
: synchronized_pool_resource(pool_options(), get_default_resource())
[Unknown/Just-In-Time compiled code] (Unknown Source:0)
libstdc++.so.6!std::pmr::synchronized_pool_resource::synchronized_pool_resource(std::pmr::pool_options const&, std::pmr::memory_resource*) (Unknown Source:0)
std::pmr::synchronized_pool_resource::synchronized_pool_resource(std::pmr::synchronized_pool_resource * const this) (/usr/include/c++/10/memory_resource:445)
__static_initialization_and_destruction_0(int __initialize_p, int __priority) (/data/solution/projects/test/source/main.cpp:10)
_GLOBAL__sub_I__Z4testRNSt3pmr26synchronized_pool_resourceE() (/data/solution/projects/test/source/main.cpp:16)
__libc_csu_init (Unknown Source:0)
libc.so.6!__libc_start_main(int ()(int, char **, char **) main, int argc, char ** argv, int ()(int, char **, char **) init, void ()(void) fini, void ()(void) rtld_fini, void * stack_end) (/build/glibc-OTsEL5/glibc-2.27/csu/libc-start.c:266)
_start (Unknown Source:0)
The chain of calls on stack explains me that the program might have been linked to libstdc++.so.6. Is this a possible reason and if so, what shall I do?
I was using
GNU gdb (Ubuntu 8.2-0ubuntu1~18.04) 8.2
for debugging. Would it be because GDB is not ready for this?
BTW: I really wasn't capable of using this editor to past images. It just doesn't show up.
You need to add -pthread to your g++ linking call. I can't fault you if you think there should be a comprehensible error message…

get process cmdline in MAC os from another C-based executable

I would like to find out if there's a sys call that gets remote process id and return it's command line in Mac OS X (the equivalent in linux is /proc/PID/cmdline.
I could use the following way of reading output of 'px ax PID' from file, but I believe there's a cleaner way.
enter code here
char sys_cmd[PATH_MAX];
snprintf(sys_cmd, PATH_MAX, "ps ax %d", pid);
fp = popen(sys_cmd, "r");
while (fgets(res, sizeof(res)-1, fp) != NULL) {
printf("%s", res);
}
pclose(fp);
Depending on exactly what you want to do, you could do something like the following with proc_pidinfo() (source code for the kernel implementation is here and header file with struct definitions is here):
$ cat procname.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/proc_info.h>
extern int proc_pidinfo(int pid, int flavor, uint64_t arg, user_addr_t buffer,
uint32_t buffersize);
#define SHOW_ZOMBIES 0
int main(int argc, char **argv) {
if(argc != 2) {
puts("Usage: procname <pid>");
return 1;
}
struct proc_taskallinfo info;
int ret = proc_pidinfo(atoi(argv[1]), PROC_PIDTASKALLINFO, SHOW_ZOMBIES,
(user_addr_t) &info, sizeof(struct proc_taskallinfo));
printf("ret=%d, result=%s\n", ret, (char *) info.pbsd.pbi_comm);
return 0;
}
$ clang procname.c -o procname 2>/dev/null
$ sudo ./procname 29079
ret=232, result=Google Chrome
I would have used dtruss on ps -p ... -o args to get an exact syscall you could use to get the right information, but unfortunately on El Capitan dtruss doesn't seem to work with some binaries (including ps) because of the following error:
$ sudo dtruss ps -p 29079 -o args
dtrace: failed to execute ps: dtrace cannot control executables signed with restricted entitlements
Instead what I did was run sudo nm $(which ps) to see what library calls were happening from ps, then I looked through those to see what looked like the most likely candidates and Googled for their implementations in the xnu (Mac OS X kernel) source code.
The correct API to do this is the KERN_PROCARGS2 sysctl, however it is very hard to use correctly (I've checked every use of this API in public code and they're all wrong), so I wrote a library to wrap its use: https://getargv.narzt.cam

"struct has no member named" error with gcc on dev machine

#include <stdio.h>
#include <stdlib.h>
#include "ReadMethods.h"
int main(int argc,char * argv[])
{
DPDA WordChecker;
DPDA * WordCheckerPointer=&WordChecker;
WordChecker.DPDAFilename=(char*)malloc(25*sizeof(char));
WordChecker.DPDAInputFilename=(char*)malloc(25*sizeof(char));
WordChecker.DPDAOutputFilename=(char*)malloc(25*sizeof(char));
strcpy( WordChecker.DPDAFilename,argv[1]);
strcpy( WordChecker.DPDAInputFilename,argv[2]);
strcpy( WordChecker.DPDAOutputFilename,argv[3]);
readDPDA(argv[1],WordCheckerPointer);
readInputLines(argv[2],WordCheckerPointer,argv[3]);
return 0;
}
This is my code that gives error from mallocs until last strcpy() ,total 6 lines.The error is "DPDA has no member named DPDAFilename" and same for other fields for every malloc and strcpy linesthat i work on.Here is the part of header file.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagRule{
char *startingState;
char symbolToPop;
char expectedInput;
char *endingState;
char symbolToPush;
}Rule;
typedef struct tagStackDPDA{
char * arrayOfSymbols;
int stackElementCount;
char * currentState;
}stackDPDA;
typedef struct tagDPDA{
char * alphabet;
char * stackSymbols;
char ** states;
char *startingState;
char **finalStates;
int finalStatesAmount;
Rule * ruleList;
stackDPDA stackOfDPDA;
int sizeArray[4];//This array holds amount values of states,alphabet symbols,stack symbols and transition rules
char *DPDAFilename;
char *DPDAInputFilename;
char *DPDAOutputFilename;
}DPDA;
The code works fine in codeblocks environment but in gcc (-Wall -ansi).Those filenames come from input text files yet i am not sure it can cause this error.
Edit:By the way I am using this command line to compile;
gcc -Wall -ansi main.c ReadMethods.h -o WordChecker
May be if you compile in C mode, you have to use C-style comments in header?
/**/ instead of //

Use variadic C functions in Go

I use shm_open with cgo. shm_open is defined with 3 arguments on Linux
int shm_open(const char *name, int oflag, mode_t mode);
whereas on OSX (Darwin) the 3rd mode flag is optional.
int shm_open(const char *name, int oflag, ...);
This creates a problem with CGO when trying to pass a mode on OSX. It complains that I pass 3 arguments, when only 2 are expected.
How can I work around this?
As usual the revelation comes 1 second after posting to SO. You can actually declare functions in the CGO comment section, so all you have to do is use a wrapper like this.
/*
#include <stdio.h>
int shm_open2(const char *name, int oflag, mode_t mode) {
return shm_open(name, oflag, mode);
}
*/
import "C"

Separating out .cu and .cpp(using c++11 library)

I am trying to convert a c++ program I have which uses random library which is a C++11 feature. After having read through a couple of similar posts here, I tried by separating out the code into three files. At the outset I would like to say that I am not very conversant at C/C++ and mostly use R at work.
The main file looks as follows.
#ifndef _KERNEL_SUPPORT_
#define _KERNEL_SUPPORT_
#include <complex>
#include <random>
#include <iostream>
#include "my_code_header.h"
using namespace std;
std::default_random_engine generator;
std::normal_distribution<double> distribution(0.0,1.0);
const int rand_mat_length = 24561;
double rand_mat[rand_mat_length];// = {0};
void create_std_norm(){
for(int i = 0 ; i < rand_mat_length ; i++)
::rand_mat[i] = distribution(generator);
}
.
.
.
int main(void)
{
...
...
call_global();
return 0;
}
#endif
The header file looks as follows.
#ifndef mykernel_h
#define mykernel_h
void call_global();
void two_d_example(double *a, double *b, double *my_result, size_t length, size_t width);
#endif
And the .cu file looks like the following.
#ifndef _MY_KERNEL_
#define _MY_KERNEL_
#include <iostream>
#include "my_code_header.h"
#define TILE_WIDTH 8
using namespace std;
__global__ void two_d_example(double *a, double *b, double *my_result, size_t length, size_t width)
{
unsigned int row = blockIdx.y*blockDim.y + threadIdx.y;
unsigned int col = blockIdx.x*blockDim.x + threadIdx.x;
if ((row>length) || (col>width)) {
return;
}
...
}
void call_global()
{
const size_t imageLength = 528;
const size_t imageWidth = 528;
const dim3 threadsPerBlock(TILE_WIDTH,TILE_WIDTH);
const dim3 numBlocks(((imageLength) / threadsPerBlock.x), ((imageWidth) / threadsPerBlock.y));
double *d_a, *d_b, *mys ;
...
cudaMalloc((void**)&d_a, sizeof(double) * imageLength);
cudaMalloc((void**)&d_b, sizeof(double) * imageWidth);
cudaMalloc((void**)&mys, sizeof(double) * imageLength * imageWidth);
two_d_example<<<numBlocks,threadsPerBlock>>>(d_a, d_b, mys, imageLength, imageWidth);
...
cudaFree(d_a);
cudaFree(d_b);
}
#endif
Please note that the __global__ has been removed from .h since I was getting the following error owing to it being compiled by g++.
In file included from my_code_main.cpp:12:0:
my_code_header.h:5:1: error: ‘__global__’ does not name a type
When I compile the .cu file with nvcc it is all fine and generates a my_code_kernel.o. But since I am using C++11 in my .cpp I am trying to compile it with g++ and I am getting the following error.
/tmp/ccR2rXzf.o: In function `main':
my_code_main.cpp:(.text+0x1c4): undefined reference to `call_global()'
collect2: ld returned 1 exit status
I understand that this might not have to do anything with CUDA as such and may just be the wrong use of including the header at both places. Also what is the right way to compile and most importantly link the my_code_kernel.o and my_code_main.o(hopefully)? Sorry if this question is too trivial!
It looks like you are not linking with my_code_kernel.o. You have used -c for your nvcc command (causes it to compile but not link, i.e. generate the .o file), I'm going to guess that you're not using -c with your g++ command, in which case you need to add my_code_kernel.o to the list of inputs as well as the .cpp file.
The separation you are trying to achieve is completely possible, it just looks like your not linking properly. If you still have problems, add the compilation commands to your question.
FYI: You don't need to declare two_d_example() in your header file, it is only used within your .cu file (from call_global()).

Resources