Identify program that connects to a Unix Domain Socket - linux

I have a program that is listening to a Unix Domain Socket.
When a client connects to the socket I'd like to find out which program connected and then decide if I allow the connection or not (based on the user/group settings).
Is this possible under Linux, and if so, how?

Yes, this is possible on Linux, but it won't be very portable. It's achieved using what is called "ancillary data" with sendmsg / recvmsg.
Use SO_PASSCRED with setsockopt
Use SCM_CREDENTIALS and the struct ucred structure
This structure is defined in Linux:
struct ucred {
pid_t pid; /* process ID of the sending process */
uid_t uid; /* user ID of the sending process */
gid_t gid; /* group ID of the sending process */
};
Note you have to fill these in your msghdr.control, and the kernel will check if they're correct.
The main portability hindrance is that this structure differs on other Unixes - for example on FreeBSD it's:
struct cmsgcred {
pid_t cmcred_pid; /* PID of sending process */
uid_t cmcred_uid; /* real UID of sending process */
uid_t cmcred_euid; /* effective UID of sending process */
gid_t cmcred_gid; /* real GID of sending process */
short cmcred_ngroups; /* number or groups */
gid_t cmcred_groups[CMGROUP_MAX]; /* groups */
};

I searched for this quite a bit, so I will show you this example on how to use SO_PEERCRED on a socket sock to get the pid/uid/gid of the peer of a socket:
int len;
struct ucred ucred;
len = sizeof(struct ucred);
if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1) {
//getsockopt failed
}
printf("Credentials from SO_PEERCRED: pid=%ld, euid=%ld, egid=%ld\n",
(long) ucred.pid, (long) ucred.uid, (long) ucred.gid);

Perhaps getpeername or getsockname could help. and I think that the permission of your unix socket are useful (not sure of that). And you might read the link inside /proc/self/fd/12 if your accept-ed socket is 12.
EDIT
using ancillary data for credentials and sendmsg is much better, as suggested by cnicutar below.

Related

get notified on connection state change with IWD

I wrote a systray area applet that displays the status of IWD backed WiFi connection. Right now my app polls iwctl station wlp4s0 show every minute and parses the result. Is there a way to avoid polling and use some sort of a notification hook?
I have found a way to do this with linux netlink protocol.
man 7 netlink
apt get install libnl-3-dev libnl-genl-3-dev
Basically:
int fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
struct sockaddr_nl snl = { .... };
bind(fd, &snl, sizeof(snl));
while (1) {
recv(fd, buf, sizeof(buf), 0);
struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
...
}
recv will block until events related to network interfaces happen, then data you need is in nlh.
For example check for new connection:
if (nlh->nlmsg_type == RTM_NEWADDR) ...

Linux kernel module to read out GPS device via USB

I'm writing a Linux kernel module to read out a GPS device (a u-blox NEO-7) via USB by using the book Linux Device Drivers.
I already can probe and read out data from the device successfully. But, there is a problem when reading the device with multiple applications simultaneously (I used "cat /dev/ublox" to read indefinitely). When the active/reading applications is cancelled via "Ctrl + C", the next reading attempt from the other application fails (exactly method call usb_submit_urb(...) returns -EINVAL).
I use following ideas for my implementation:
The kernel module methods should be re-entrant. Therefore, I use a mutex to protect critical sections. E.g. allowing only one reader simultaneously.
To safe ressources, I reuse the struct urb for different reading requests (see an explanation)
Device-specific data like USB endpoint address and so on is held in a device-specific struct called ublox_device.
After submitting the USB read request, the calling process is sent to sleep until the asynchronous complete handler is called.
I verified that the ideas are implemented correctly: I have run two instances of "cat /dev/ublox" simultaneously and I got the correct output (only one instance accessed the critical read section at a time). And also reusing the "struct urb" is working. Both instances read out data alternatively.
The problem only occurs if the currently active instance is cancelled via "Ctrl + C". I can solve the problem by not reusing the "struct urb" but I would like to avoid that. I.e. by allocating a new "struct urb" for each read request via usb_alloc_urb(...) (usually it is allocated once when probing the USB device).
My code follows the USB skeleton driver from Greg Kroah-Hartman who also reuse the "struct urb" for different reading requests.
Maybe someone has a clue what's going wrong here.
The complete code can be found on pastebin. Here is a small excerpt of the read method and the USB request complete handler.
static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
return_value = mutex_lock_interruptible(&ublox_device->bulk_in_mutex);
if (return_value < 0)
return -EINTR;
...
retry:
usb_fill_bulk_urb(...);
ublox_device->read_in_progress = 1;
/* Next call fails if active application is cancelled via "Ctrl + C" */
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
if (return_value) {
printk(KERN_ERR "usb_submit_urb(...) failed!\n");
ublox_device->read_in_progress = 0;
goto exit;
}
/* Go to sleep until read operation has finished */
return_value = wait_event_interruptible(ublox_device->bulk_in_wait_queue, (!ublox_device->read_in_progress));
if (return_value < 0)
goto exit;
...
exit:
mutex_unlock(&ublox_device->bulk_in_mutex);
return return_value;
}
static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
int status = urb->status;
/* Evaluate status... */
...
ublox_device->transferred_bytes = urb->actual_length;
ublox_device->read_in_progress = 0;
wake_up_interruptible(&ublox_device->bulk_in_wait_queue);
}
Now, I allocate a new struct urb for each read request. This avoids the problem with the messed up struct urb after an active read request is cancelled by the calling application. The allocated struct is freed in the complete handler.
I will come back to LKML when I optimize my code. For now, it is okay to allocate a new struct urb for each single read request. The complete code of the kernel module is on pastebin.
static ssize_t ublox_read(struct file *file, char *buffer, size_t count, loff_t *pos)
{
struct ublox_device *ublox_device = file->private_data;
...
retry:
ublox_device->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
...
usb_fill_bulk_urb(...);
...
return_value = usb_submit_urb(ublox_device->bulk_in_urb, GFP_KERNEL);
...
}
static void ublox_read_bulk_callback(struct urb *urb)
{
struct ublox_device *ublox_device = urb->context;
...
usb_free_urb(ublox_device->bulk_in_urb);
...
}

Dynamic pool of processes

I'm writing a client-server (TCP) program in C on a Unix system. The client sends some information and the server answers. There's only one connection per child process. New connections use pre-running processes from a pool, and the pool size is dynamic, so if the number of free processes (processes not servicing a client) drops too low, it should create new processes, and likewise if it gets too high extra processes should be terminated.
This is my server code. Every connection make a new child process using fork(). Each connection runs in a new process. How can I make a dynamic pool like I explained above?
int main(int argc, char * argv[])
{
int cfd;
int listener = socket(AF_INET, SOCK_STREAM, 0); //create listener socket
if(listener < 0){
perror("socket error");
return 1;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
int binding = bind(listener, (struct sockaddr *)&addr, sizeof(addr));
if(binding < 0){
perror("binding error");
return 1;
}
listen(listener, 1); //listen for new clients
signal(SIGCHLD,handler);
int pid;
for(;;) // infinity loop on server
{
cfd = accept(listener, NULL, NULL); //client socket descriptor
pid = fork(); //make child proc
if(pid == 0) //in child proc...
{
close(listener); //close listener socket descriptor
... //some server actions that I do.(receive or send)
close(cfd); // close client fd
return 0;
}
close(cfd);
}
If you have several processes blocked in accept on the same listen socket, then a new connection that comes in will get delivered to one of them. (Depending, several may wake up, but only one will actually get the connection). So you need to fork several children after listen, but before accept. After handling a request, the child goes back to accept instead of exit. That handles (1) and (2).
(3) is harder. You need some form of IPC. Typically, you'd have a parent process that just manages having the right number of children. Your child processes need to use IPC to tell the parent how busy they are. The parent can then either fork more children (which go into the accept loop above) or send signals to children to tell them to finish up and exit. It should also handle waiting on children, handle unexpected deaths, etc.
The IPC you want to use is probably shared memory. Your two options are SysV (shmget) and POSIX (shm_open`) shared memory. You probably want the latter if available. You'll have to deal with synchronizing access (both POSIX and SysV provide semaphores to help with this, again prefer POSIX) or using atomic access only.
(You probably don't actually want a process to exit the instant there are more than X free children, that'll lead to repeatedly reaping and spawning them, which is expensive. Instead you probably want some measure of how utilized they were over the last second... So your data is more complicated than a bitmap of in use/free.)
There are a lot of daemons that work like this, so you can fairly easily find code examples. Of course, if you go look at Apache, you'll probably find it more complicated, to get good performance and be portable everywhere.

Develop simple net_device in the linux kernel

I am trying to implement a netdevice (net_device) in linux kernel. This is simple net_device which pass the command/data from user space to kernel space and vice versa this is the goal of this simple net_device. I am using socket for passing command/data from user space to kernel space . After googling i successed in registering net_device and able to see my device in /sys/class/net/abc0 (device name)
when coming to file operation there is no clear idea of the flow
struct net_device_ops
{
.ndo_open =open,
.ndo_close = close,
.ndo_start_xmit = start_xmit
}
if i issue write in socket will it call start_xmit in data link layer.
If i want to call open method, how to call it using socket
How to call start_xmit using socket
How will i find , there is data packet in the receive buffer and pass it to user space.
There is no clear flow/information about simple net_device (except ethernet) can any suggest a link/pdf.
I tried writing simple socket program to test open,close,start_xmit. where socket read/write is not calling open,close,star_xmit .
Is there any way to test the developed net_device ?
Thank you
I found how to test the open,close function .
type : ifconfig abc0(Device name) up will call open method
type : ifconfig abc0(Device name) down will call close method
Can some one help me how to test these methods with sockets.
SIOCSIFFLAGS, -> IFF_UP you can actually set or unset it while doing an ioctl to the netdevice abc0.
first off you have to create a dgram socket,
then use ifreq structure defined in net/if.h
and fill interface and iff_flags
iff_flags can be set with IFF_UP or can be negated with the same IFF_UP to make interface down
and then close the socket.
#include <net/if.h>
....
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
goto fail;
}
struct ifreq ifreq;
strcpy(ifreq.ifr_name, "abcd0");
ifreq.iff_flags |= IFF_UP;
if (ioctl(sock, &ifreq, sizeof(ifreq) < 0) {
perror("ioctl setting interface up");
}
ifreq.iff_flags ~= IFF_UP;
if (ioctl(sock, &ifreq, sizeof(ifreq) < 0) {
perror("ioctl setting interface down");
}
close(sock);
offtopic:
will you please share your code? we can understand too about your network device :)

How to get the device type associated with a fd

i get a valid "fd" object from a caller. How can i find out what is the fd type - whether it is referring to a File, Socket, Device, etc?
Depending on the refered type, i need to execute specific functions, say if the fd is associated with a File, then i need to do a read. If it is associated with a socket, then i need to get the socket properties.
Well, in theory at least, you still do a read for a socket, and for a device, and for a pipe, and.... :-P
If you want more data from the socket, such as the socket addresses, you can just call the functions for doing that. It will simply fail for non-sockets, and it's up to you to decide how you want to deal with that.
If you really must know, do an fstat on your file descriptor, then look at its mode (st_mode):
mode_t type;
struct stat fdstat;
/* ... */
if (fstat(fd, &fdstat) == -1)
/* error out */
type = fdstat.st_mode & S_IFMT;
switch (type) {
case S_IFSOCK:
/* socket */
case S_IFIFO:
/* FIFO */
/* other cases */
}

Resources