Retrieving session Id in linux kernel (Kernel Space) - linux

I want to retrieve the sessionid of the current process in linux kernel (Kernel Space). I saw task_struct has a field sessionid but it is defined only when the macro CONFIG_AUDITSYSCALL is ON. So i tried to build the kernel with this macro ON but still i was not getting the result. Also I tried getting its value from function with CONFIG_AUDITSYSCALL on audit_get_sessionid(current) but was getting either -1 or junk value ( different from getsid(0) method in user space).
I am struck at this point. Any suggestion would be of great help.

You can take a look at the getsid syscall at here: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=kernel/sys.c#l1106
SYSCALL_DEFINE1(getsid, pid_t, pid)
{
struct task_struct *p;
struct pid *sid;
int retval;
rcu_read_lock();
if (!pid)
sid = task_session(current);
else {
...
Which suggest you can use the kernel function task_session() to get the session id.

pid_vnr(task_session(current)); would do what u want!!

Related

How can i print current time in kernel?

i'm a beginner of linux. (sorry about my poor english)
I should print current time and do something through system call in linux.
I did other things but failed to print current time..
I wrote like
#include<linux/kernel.h>
#include<linux/time.h>
...
asmlinkage long sys_printtime(void) {
...
struct timeval time;
struct tm tm1;
...
do_gettimeofday(&time);
local_time=(u32)(time.tv_sec -(sys_tz.tz_minuteswest * 60));
time_to_tm(local_time,(3600*9),&tm1);
printk(KERN_DEBUG "time #(%04d-%02d-%02d %02d:%02d:%02d)\n", tm1.tm_year+1900,tm1.tm_mon+1,tm1.tm_mday,tm1.tm_hour,tm1.tm_min,tm1.tm_sec);
...
return 0;
}
but it doesn't work.
The error said i can not use do_gettimeofday, and i finally knew that i can not use do_gettimeofday anymore because kernel5 doesn't support.
I searched on google and stackoverflow,
but i don't know how to print current time in kernel5..
anybody can help me?
Yes, do_gettimeofday has been removed because of y2038 problem. Instead the kernel provides time interfaces which you can use as per your need. Check the documentation https://www.kernel.org/doc/html/latest/core-api/timekeeping.html.
For example, you have ktime_get_ts64(struct timespec64 *ts) which will provide you time in seconds and nanoseconds.
struct timespec64 {
time64_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
If you only want in nanoseconds, you can use u64 ktime_get_ns(void). Please check the documentation above for what suits your purpose.
Also you can check timekeeping.h and ktime.h for further information.
If you want to find an example just search the function name in the kernel source either using grep -rni <func name> or use cscope. You can also search it online here
There is also a one liner to get the rtc time like this:
#include <linux/ktime.h>
#include <linux/rtc.h>
struct rtc_time t = rtc_ktime_to_tm(ktime_get_real());
printk(KERN_INFO "%ptRs", &t);
Document of ktime_get_real can be found here.
I didn't find any documentation for rtc_ktime_to_tm even in the code but it gets the time as Unix epoch in nano seconds as input and outputs struct rtc_time. How to print struct rtc_time can be found here.

How the function works cdev_add()?

Do I understand correctly that when the structure is initialized
struct dev_t dev;
dev = MKDEV(major,minor_first);
I create only the device file, it's right to say - to the node. Next, should I indicate how I will work with this device? To do this, you need the function
cdev_add(&my_ch_dev, dev, minor_count);
after
cdev_init(&my_ch_dev ,&dev_fops);
So, I mean that my driver will work with the created node as a character device? Thanks in advance!
Here is the details how it works
dev = MKDEV(major,minor_first);
Still kernel doesn't know whether we selected major/minor number or not, so for this you need to register he device by calling register_chrdev_region()
register_chrdev_region(dev,minor_count,"AYRAT_DEVICE"); so till now number(major/minor) has reserved the name(dev) so that other driver will not get the same name. Next you need to register your driver with kernel.
register with cdev by calling cdev_init(&my_ch_dev ,&dev_fops); Next you need to inform to kernel that we filled all member of struct cdev, so for this use cdev_add().
cdev_add(&my_ch_dev, dev, minor_count);

How to find owner socket of sk_buff in Linux kernel?

I'm trying to find the owner socket of an sk_buff instance, say, skb. My ultimate goal is to find a specific TCP option and somehow let the user space application to know. I plan to set a socket option when I find the TCP option and let the user space app to call getsockopt(). Therefore I need to know the ownership between sk_buff and sock.
I find there is a field in sk_buff:
struct sock *sk;
However, when I try to retrieve this field at tcp_parse_options in tcp_input.c, I always get skb->sk == NULL.
So I'm wondering how can I find the owner here?
Also, I find 3 places that seems to set the owner socket:
http://lxr.free-electrons.com/source/net/ipv4/tcp_input.c?v=3.11#L4181
http://lxr.free-electrons.com/source/net/ipv4/tcp_input.c?v=3.11#L4196
http://lxr.free-electrons.com/source/net/ipv4/tcp_input.c?v=3.11#L4456
I also add a new flag in sk_buff for indicating and set it at tcp_parse_options. Then I check this flag at these three places. But none of them shows the flag is set so that I cannot determine whether to set the socket option.
Any idea or suggestion for this problem?
Thanks in advance!
From the sk_buff (skb) you can get the sock (sk) with something like this:
const struct tcphdr *th = tcp_hdr(skb);
struct sock *sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
if (sk)
struct socket* = sk->sk_socket;
That worked for me. Don't forget to add the right headers.

How to create an execve() child process with the right tty settings to run 'vi' yet still redirect IO back to the parent process?

How do I get a forked, execve() child process that can run 'vi', etc. and redirect all IO to the parent process?
I'm trying to pass shells through from an embedded Linux process to the PC software interface connected over the network. The IO for the shell process is packaged into app-specific messages for network transport over our existing protocol.
First I was just redirecting IO using simply pipe2(), fork(), dup2(), and execve(). This didn't give me a tty on the remote side, so screen, etc. didn't work.
Now I'm using forkpty, and screen mostly works, but many many other don't (vi, stty, etc). It appears the current problem is that the child process doesn't control the tty.
I've been experimenting with TIOCSCTTY, but haven't had much luck.
Here's more or less what I've got:
bool ExternalProcess::launch(...)
{
...
winsize winSize;
winSize.ws_col = 80;
winSize.ws_row = 25;
winSize.ws_xpixel = 10;
winSize.ws_ypixel = 10;
_pid = forkpty(&_stdin, NULL, NULL, &winSize);
//ioctl(_stdin, TIOCNOTTY, NULL);
if (!_pid && (_pid != -1))
{
// this is the child process
char tty[4096];
strncpy(tty, ttyname(STDIN_FILENO), sizeof(tty));
tty[sizeof(tty)-1]=0;
FILE* fp = fopen("debug.txt", "wt"); // no error checking - temporary test code
fprintf(fp, "slave TTY %s", tty);
//if (ioctl(_stdin, TIOCSCTTY, NULL) < 0)
if (ioctl(STDIN_FILENO, TIOCSCTTY, NULL) < 0)
{
fprintf(fp, "ioctl() TIOCSCTTY %s\n", strerror(errno));
fflush(fp);
}
else
{
fprintf(fp, "SET CONTROLLING TTY!");
fflush(fp);
}
fclose(fp);
// command, args, env populated elsewhere
execve(command, args, env);
...
// fail path
_exit(-1);
return false;
}
_stdout = _stdin;
...
// enter select() loop reading/writing _stdin, _stdout
}
I am getting results in the debug file like:
slave TTY /dev/pts/5
SET CONTROLLING TTY!
but still many apps are failing with tcsetattr() errors. Am I right in thinking this is a controlling tty problem? How do I fix it?
EDIT
Minor correction. When I do the ioctl TIOCSCTTY on STDIN_FILENO, then it works as in the debug file above, but the IO redirection back to the parent process is disrupted.
EDIT 2
Okay, I'm starting to understand this better. Looking at the kernel source for the ioctl behind tcsetattr(), the processes I am calling are being sent SIGTTIN and SIGTTOU when trying to change the tty.
Only a foreground process can do that, and they're running as if they're background processes. I tried setting those signals to SIG_IGN after forking and before the execve(), but that didn't work. The semantics of this I understand, but it's safe in my redirection scenario for the execve()'d processes to act as if they're foreground processes. The question is... how to make it so? I will continue to search in the kernel code for clues.
Ugh! It's bash, the shell I was calling with execve().
If it detects that stderr is not attached to a tty, then it enters this special mode where child processes cause SIGTTOU.
I found a mention of this problem here.
When I stopped redirecting stderr away from the tty, then it now seems to work as planned.

Get starting address of a memory page in Linux

In my code, I need to keep track of some pages which are being modified. Initially I give only read access to them, but on the signal handler I give them both read and write access (I am not going to explain what is the purpose for all that and there is actually more code in the signal handler, which I've not shown).
Now my question is how to get the starting address of a page from a memory address which resides in that page. So basically I need to implement the get_page_start_addr shown here in the code. Up till now, I was only doing it for a single page, whose starting address my program knew. But now, since I need to do it for multiple pages, I need to get the starting address of the page from any arbitrary memory address, because mprotect only accepts starting page address as valid argument.
static void memory_change_handler(int sig, siginfo_t *si, void *unused)
{
long addr = (long)si->si_addr;
long page_start_addr = get_page_start_addr( addr );
if (mprotect((void*)page_start_addr, pagesize, PROT_READ | PROT_WRITE) == -1)
{
print_error();
handle_error("mprotect");
}
}
In Linux (in other OSes too, I guess), pages are aligned at page boundaries. Thus, if you know your PAGE_SIZE, then you can simply get the start of the page by masking the lower address bits.
page_start = addr & ~(PAGE_SIZE-1);
To portably know your pagesize, use sysconf(_SC_PAGESIZE).
You can take that address (unsigned long) /pagesize and *pagesize.
This gives you the first page address of your logical address.

Resources