Is there a way to see active mappings from virtual to physical memory in Linux?
To make simpler, let's assume we are on 32 bit system
Kernel Virtual Addresses
>>> 0xffffffff-0xc0000000
1073741823
Userspace Virtual Addresses
>>> 0xc0000000-0x00000000
3221225472
I want to scan Kernel Virtual Addresses for task_struct structure and was wondering if I have to scan the whole range or there is somehow a mapping which kernel virtual addresses are currently used?
Update 1:
How can I read it programatically to view all active mappings?
As I said I want to spare me going though the whole address space:
My code so far:
Here I try to scan the whole address space to look for task_struct and find the process name and PID (based on struct offsets)
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdbool.h>
void main()
{
int fd;
char *retp = NULL;
fd = open("/dev/mem", O_RDWR|O_SYNC);
for(int z=0;z<=0xffffffff;z=z+4096)
{
retp = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd,z);
if (retp == MAP_FAILED)
{
printf("FAILED\n");
}
else
{
printf("PASSED\n");
char task_struct[5760];
int pid;
for(int i=0;i<4096;i++)
{
memcpy(&task_struct,retp+i,5760);
memcpy(&pid,task_struct+768,sizeof(int));
if(strcmp(task_struct+996,"bash")==0)
printf("addr:%p\tname:%s\tpid:%i\n",retp+i,task_struct+996,pid);
}
munmap(retp,4096);
}
}
close(fd);
}
Related
I'm debugging some odd fails with reading from shared memory, and for debugging purposes I'd like to put some prints that show me currently mmaped size. So, for example, I have this code:
#include <cstdio>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <utility>
std::pair<int, void*> make_shm() {
const int shm = shm_open("foo", O_RDONLY | O_CREAT, S_IRWXO | S_IRWXG | S_IRWXU);
if (shm == -1) {
perror("connect_to_shm: shm_open failed");
return {-1, nullptr};
}
void* shm_ptr = mmap(nullptr, 15360000, PROT_READ, MAP_SHARED, shm, 0);
if (shm_ptr == MAP_FAILED) {
perror("connect_to_shm: mmap failed");
close(shm);
return {-1, nullptr};
}
return {shm, shm_ptr};
}
int main() {
auto [shm, shm_ptr] = make_shm();
// how do I print the mmapped size?
}
How do I derive the 15360000 size from the shm and shm_ptr?
I tried searching, but all results I'm getting for "get size of shared memory" are either about memory limits, or about sizes of pages. The closest I found was this question, but it's for Solaris and unanswered anyway.
I am trying to call inotify_add_watch to watch a file. I would like to specify the file relative to an O_PATH | O_DIRECTORY file descriptor, a la symlinkat, fstatat, or openat.
Is this possible? It doesn't look like it is. Anyone know of a workaround?
EDIT
The closest thing seems to be the "trick" described at man 2 open under "Rationale for openat". See the answer by user1643723 for an example.
You can use symlinks, provided by procfs to achieve the functionality of most *at calls. Open a directory descriptor and use /proc/self/fd/<dir descriptor>/filename instead of the full path to filename:
#define _GNU_SOURCE
#include <sys/stat.h>
#include <sys/inotify.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
int main() {
int inotify = inotify_init();
mkdir("tmp", 0777);
mknod("tmp/foo", 0777 | S_IFREG, 0);
int dirFd = open("tmp", O_DIRECTORY | O_PATH);
char buf[40] = { '\0' };
sprintf(buf, "/proc/self/fd/%d/foo", dirFd);
int watchd = inotify_add_watch(inotify, buf, IN_MOVE | IN_ATTRIB);
if (watchd < 0) {
printf("Failed: %s", strerror(errno));
} else {
printf("ok");
}
}
The program above prints "ok" on Linux 4.4.x.
I wonder to understand where fcntl c++ function saves information about locked files. I know that it saves some information on /proc/locks , but fcntl identify lock even if it locked by another host
In my first host I locked some file By F_WRLCK.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include<iostream>
main() {
int fd;
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_start=0;
lock.l_whence= SEEK_SET;
lock.l_len=0;
printf("open %d\n",fd=open("/u/embedit/places/scratch/gtevos/ts16nxq42p11assrl16kaa03/ts16nxq42p11assrl16kaa.cpj", O_RDWR ));
int rc = fcntl(fd, F_SETLK, &lock);
std::cout<<rc<<std::endl;
std::cin>>fd;
}
When I am traying to lock the same file on my second host by F_RDONLY it doesn't work.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include<iostream>
main() {
int fd;
struct flock lock;
lock.l_type=F_RDLCK;
lock.l_start=0;
lock.l_whence= SEEK_SET;
lock.l_len=0;
printf("open %d\n",fd=open("/u/embedit/places/scratch/gtevos/ts16nxq42p11assrl16kaa03/ts16nxq42p11assrl16kaa.cpj", O_RDONLY ));
int rc = fcntl(fd, F_SETLK, &lock);
std::cout<<rc<<std::endl;
std::cin>>fd;
}
I just want to understand which mechanism is used that provide ability to right identify locks.
I try to use setsockopt with the flag IPT_SO_SET_REPLACE but i keep getting the wired error from errno Protocol not available this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <linux/sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <fcntl.h>
int main(void) {
int sock;
int ret;
void *data;
size_t size;
struct ipt_replace *repl;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("socket");
return -1;
}
size = sizeof(struct ipt_replace);
data = malloc(size); Protocol not available
if (data == NULL) {
perror("malloc");
return -1;
}
memset(data, 0, size);
repl = (struct ipt_replace *) data;
repl->num_counters = 0x1;
repl->size = 0xffffffff;
repl->valid_hooks = 0x1;
repl->num_entries = 0x1;
ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, size);
printf("\ndone %d\n", ret);
perror("error: ");
return 0;
}
this is the output :
sock:3
data:
size:92
done -1
error: : Protocol not available
Looking briefly at the kernel code, this would seem to indicate that the IP tables module isn't available (i.e. the kernel wasn't built with it configured, or it can't be found or loaded).
It appears to me that for a socket of the kind you created, the code flow is:
enter raw_setsockopt: level != SOL_RAW so...
call ip_setsockopt: level == SOL_IP but option isn't any of the IP_xxx options so...
call nf_setsockopt: Search loaded netfilter modules for one that has registered IPT_SO_SET_REPLACE.
I think the last must have failed, so you get ENOPROTOOPT back (== Protocol not available)
I was reading about ptrace on the net and found that a process can request to trace another process by using PTRACE_ATTACH but apparently all the examples available involve the use of fork().
What I want is to have 2 programs - prg1.c and prg2.c where prg2.c should trace prg1.c. I tried using PTRACE_ATTACH in prg2.c but it seems that the call failed - prg2.c couldn't trace prg1.c . How does ptrace work ? Can anybody explain ?
Code for prg1.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main()
{
printf("Hello world\n");
sleep(20);
execl("/bin/ls", "ls", NULL);
return 0;
}
Code for prg2.c :
#include <stdio.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc , char **argv)
{
int pid = atoi(argv[1]);
int status;
if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) {
printf("ptrace attach failed!");
return 0;
}
wait(&status);
sleep(5);
ptrace(PTRACE_DETACH, pid, NULL, NULL);
return 0;
}
I have included a sleep() to get the pid of prg1's executable(during that time) using ps -af and give it as an input to the executable of prg2.