Associate text with a mutex - winapi

I have a program that checks only one copy of itself is running: (C++ pseudocode)
int main()
{
HANDLE h_mutex = CreateMutex(NULL, TRUE, "MY_APP_NAME");
if ( !h_mutex )
{
ErrorMessage("System object already exists");
return EXIT_FAILURE;
}
else if ( GetLastError() == ERROR_ALREADY_EXISTS )
{
ErrorMessage("App is already running");
return EXIT_FAILURE;
}
// rest of code
ReleaseMutex(h_mutex);
CloseHandle(h_mutex);
return 0;
}
I would like to improve the error message "App is already running", and instead have it say "App is already running - started by USER at DATETIME, pid PID, OTHERINFO".
Is it possible for the first instance of my application to "register" a text string when creating the Mutex (or just after that); so that when another instance of my application detects that the Mutex already exists, it it can retrieve that text string and display that information?

You could use CreateFileMapping and MapViewOfFile to share a structure between the existing process and the newly started process. You would need to create a named Event as well as the mutex that you already create to ensure that any information your store in the mapping is initialized before you try to read it in the new process.
The basic process would be:
Create the mutex as you do now.
If the mutex did not previously exist then you will use CreateFileMapping to create a named mapping backed by the page file (you'll pass INVALID_HANDLE_VALUE as the file handle). Use MapViewOfFile to map the section into the process address space. Initialize the contents of the shared memory with whatever information you want to share, remember that the address of the shared block will (likely) be different between processes, so don't use any pointers in the data. If you must, you offsets from the mapped address to make references (only within the shared section). Use CreateEvent to create a named manual reset event, use SetEvent to set the named event.
If the mutex existed previously, use CreateEvent to create the named event mentioned in the previous paragraph. Use WaitForSingleObject (or any other wait function) to wait for the named event to become signaled. This wait ensures that the original process has had a chance to initialize the contents of the shared section. Use CreateFileMapping and MapViewOfFile to map the shared section into the process address space and read whatever information you chose to store in the shared area.
Eventually, CloseHandle everything and exit.
As a side note, you do not need to take ownership of the mutex when creating it. The mutex in this case is really just a named object that you can determine whether or not it existed before you tried to create it. You chould use a semaphore, event, or even the shared section from CreateFileMapping.

You can do a lot of thing. You can store the text in a file and when your application opens, read it to check Mutex name. Or you can store it in Registry. Or you can send message to your application window. Still there is ways to do such a thing. You should decide which one is best fit for your application.

Related

Why does WriteProcessMemory need the handle value passed in, not the ID of the target process?

In the Windows system, we can modify the memory of another process across processes. For example, if process A wants to modify the memory of process B, A can call the system function WriteProcessMemory. The approximate form is as follows:
BOOL flag = WriteProcessMemory(handler, p_B_addr, &p_A_buff, write_size); ...
This function return a Boolean value, which represents whether the write operation is successful. It needs to pass four parameters, let's take a look at these four parameters:
handler. This is a process handle, and it can be used to find B process.
p_B_addr. In process B, the address offset to be written into memory.
p_A_buff. In process A, the pointer to the write data buffer.
write_size. The number of bytes to write.
I am confused about the first parameter handler, which is a variable of type HANDLE. For example, when our program is actually running, the ID of process B is 2680, and then I want to write memory to process B. First I need to use this 2680 to get the handle of process B in process A. The specific form is handler=OpenProcess(PROCESS_ALL_ACCESS, FALSE, 2680), and then you can use this handler to fall into the kernel to modify the memory of process B.
Since they are all trapped in kernel functions to modify memory across processes, why is the WriteProcessMemory function not designed to be in the form of WriteProcessMemory(B_procID, p_B_addr, &p_A_buff, write_size)?
Among them, B_procID is the ID of the B process, since each process they all have unique IDs. Can the system kernel not find the physical address that the virtual address of the B process can map through this B_procID? Why must the process handle index of the B process in the A process be passed in?
There are multiple reasons, all touched on in the comments.
Lifetime. The process id is simply a number, knowing the id does not keep the process alive. Having a open handle to a process means the kernel EPROCESS structure and the process address space will stay intact, even if said process finishes by calling ExitProcess. Windows tries to not re-use the id for a new process right away but it will happen some time in the future given enough time.
Security/Access control. In Windows NT, access control is performed when you open a object, not each time you interact with the object. In this case, the kernel needs to know that the caller has PROCESS_VM_WRITE and PROCESS_VM_OPERATION access to the process. This is related to point 3, efficiency.
Speed. Windows could of course implement a WriteProcessMemoryById function that calls OpenProcess+WriteProcessMemory+CloseHandle but this encourages sub optimal design as well as opening you up to race conditions related to point 1. The same applies to "why is there no WriteFileByFilename function" (and all other Read/Write functions).

How to handle device removal in Linux Kernel Driver?

You have done it a thousand times: you unplug some USB equipment and any device associated with that USB equipment is removed by the driver. Any program that uses some previously opened file handle will get an error. Somehow most Linux drivers take care of that.
I am currently struggling to implement the same in a simple driver. My driver creates a character device. When the device is opened, I set the private_data member of struct file to the address of some management data that exists once per character device. That management data also includes a mutex that I use to synchronize operations like read, write, and ioctl.
The problem now arises when the USB equipment is unplugged. I must not free the memory where that management data lives. First, any currently running read, write, or ioctl should finish. Any such running call will likely also hold a lock on the mutex and will attempt to unlock it. So the memory where the mutex lives will be accessed.
Any read, write, or ioctl call subsequent to unplugging the equipment should fail, so every such call must read some variable telling whether the USB equipment is still plugged in or not. Again, that variable must live somewhere and the memory where it lives must stay allocated as long as there are open file handles.
Long story short, it seems to me that I must do some sort reference counting: The management data must stay allocated until all file handles have been closed. I could implement that myself, but I have the feeling that I would reinvent the wheel. Such a thing must already exist, I'm not the first to have this problem.
Does Linux internally keep track of the number of open file handles? Can I define a callback that is called when all file handles have been closed? Is that even a viable thing? What is the proper way to remove a character device from the system?
Global variables shall not be avoided, since any number of USB devices can be attached.
As suggested by 0andriy, I have used reference counting to track the number of open file handles. Per character device, I have added a new struct containing a mutex, a kref, the cdev struct, and a pointer to further data. I use kref_get to increase the reference counter when a new file handle is opened. Accordingly, I use kref_put when file handles are released or the USB equipment is unplugged.
Since all I/O operations (read, write, ioctl, etc.) use the mutex, I can safely change the pointer to NULL when the USB equipment is unplugged. The I/O operations then start reporting errors.
The kref reference counter only returns to zero when the USB equipment is unplugged and all file handles are closed. So then I can also free the memory of the new struct.
This seems to work. It was a surprise that the cdev struct is referenced by file handles. It seems to be needed as long as there are open file handles.
But I'm still surprised that I had to go down this route. It seems redundant to implement that in every driver.
UPDATE: As it turns out, doing reference counting yourself is dangerous. In particular counting the number of open file handles is wrong. There is a whole reference-count-based garbage collection system in Linux and you need to use it.
For example, Linux calls cdev_get when a process opens a character device and cdev_put when the process exists and the file handle is still open. Unfortunately, the call to cdev_put would occur after the file handle's release function. As we would free the memory after the last file handle has been released, we would end up freeing the underlying memory of the cdev and the mutex before cdev_put is called.
The solution is to assign a parent to the cdev via cdev_set_parent. The parent kobject will have its reference counter increased whenever cdev_get is called and decreased after cdev_put is called. The kobject then can have its own release function which frees any memory required by the cdev. Basically I replaced the kref in my struct with a kobject.
Lesson learned: don't do reference counting on your own. Use the existing hierarchy of kobjects, which is the kernel's way of doing garbage collection.
UPDATE2: It turns out, we reinvented the wheel again. The device struct includes a release hook, which is called when the internal kobject reached a reference count of zero. This is the mechanism typically used in the kernel to release resources associated with an device - including the device struct itself.
I was looking for a release hook in the cdev struct. There was none. But it turns out I should have looked one step up in the hierarchy for such a hook.
Long story short: Use cdev_device_add in combination with the device release hook. cdev_device_add will internally call cdev_set_parent, so the device becomes the parent of the cdev. Those are the mechanism other kernel drivers (e.g. evdev) use to release their resources.

who creates map in BPF

After reading man bpf and a few other sources of documentation, I was under impression that a map can be only created by user process. However the following small program seems to magically create bpf map:
struct bpf_map_def SEC("maps") my_map = {
.type = BPF_MAP_TYPE_ARRAY,
.key_size = sizeof(u32),
.value_size = sizeof(long),
.max_entries = 10,
};
SEC("sockops")
int my_prog(struct bpf_sock_ops *skops)
{
u32 key = 1;
long *value;
...
value = bpf_map_lookup_elem(&my_map, &key);
...
return 1;
}
So I load the program with the kernel's tools/bpf/bpftool and also verify that program is loaded:
$ bpftool prog show
1: sock_ops name my_prog tag f3a3583cdd82ae8d
loaded_at Jan 02/18:46 uid 0
xlated 728B not jited memlock 4096B
$ bpftool map show
1: array name my_map flags 0x0
key 4B value 8B max_entries 10 memlock 4096B
Of course the map is empty. However, removing bpf_map_lookup_elem from the program results in no map being created.
UPDATE
I debugged it with strace and found that in both cases, i.e. with bpf_map_lookup_elem and without it, bpftool does invoke bpf(BPF_MAP_CREATE, ...) and it apparently succeeds. Then, in case of bpf_map_lookup_elem left out, I strace on bpftool map show, and bpf(BPF_MAP_GET_NEXT_ID, ..) immediately returns ENOENT, and it never gets to dump a map. So obviously something is not completing the map creation.
So I wonder if this is expected behavior?
Thanks.
As explained by antiduh, and confirmed with your strace checks, bpftool is the user space program creating the maps in this case. It calls function bpf_prog_load() from libbpf (under tools/lib/bpf/), which in turn ends up performing the syscall. Then the program is pinned at the desired location (under a bpf virtual file system mount point), so that it is not unloaded when bpftool returns. Maps are not pinned.
Regarding map creation, the magic bits also take place in libbpf. When bpf_prog_load() is called, libbpf receives the name of the object file as an argument. bpftool does not ask to load this specific program or that specific map; instead, it provides the object file and libbpf has to deal with it. So the functions in libbpf parse this ELF object file, and eventually find a number of sections corresponding to maps and programs. Then it tries to load the first program.
Loading this program includes the following steps:
CHECK_ERR(bpf_object__create_maps(obj), err, out);
CHECK_ERR(bpf_object__relocate(obj), err, out);
CHECK_ERR(bpf_object__load_progs(obj), err, out);
In other words: start by creating all maps we found in the object file. Then perform map relocation (i.e. associate map index to eBPF instructions), and at last load program instructions.
So regarding your question: in both cases, with and without bpf_map_lookup_elem(), maps are created with a bpf(BPF_MAP_CREATE, ...) syscall. After that, relocation happens, and program instructions are adapted to point, if needed, to the newly created maps. Then once all steps are finished and the program is loaded, bpftool exits. The eBPF program should be pinned, and still loaded in the kernel. As far as I understand, if it does use the maps (if bpf_map_lookup_elem() was used), then maps are still referenced by a loaded program, and are kept in the kernel. On the other hand, if the program does not use the maps, then there is nothing more to hold them back, so the maps are destroyed when the file descriptors held by bpftool are closed, when bpftool returns.
So in the end, when bpftool has completed, you have a map loaded in the kernel if the program uses it, but no map if no program would rely on it. Sounds like expected behaviour in my opinion; but please do ping one way or another if you experience strange things with bpftool, I'm one of the guys working on the utility. One last generic observation: maps can also be pinned and remain in the kernel even if no program uses them, should one need to keep them around.
I was under impression that a map can be only created by user process.
You're completely right - user programs are the ones that invoke the bpf system call in order to load eBPF programs and create eBPF maps.
And you did just that:
So I load the program with tools/bpf/bpftool and ...
Your bpftool program is the user process that is invoking the bpf syscall, and thus is the user process that is creating the eBPF map.
BPF programs don't have to be unloaded when the user program that created it quits - bpftool likely uses this mechanism.
Some relevant bits from the man page to connect the dots:
A user process can create multiple maps ... and access them via file descriptors.
Generally, eBPF programs are loaded by the user process and automatically unloaded when the process exits. In some cases ... the program will continue to stay alive inside the kernel even after the process that loaded the program exits.
Each eBPF program is a set of instructions that is safe to run until its completion. ... During verification, the kernel increments reference counts for each of the maps that the eBPF program uses, so that the attached maps can't be removed until the program is unloaded.

Who read/write my application's memory

Each Application has its memory space. In Windows, all process can use "OpenProcess" and "ReadProcessMemory/WriteProcessMemory(NtReadVirtualMemory/NtWriteVirtualMemory)" to read or write memory of application.
In System kernel, we can hook SSDT function "NtReadVirtualMemory/NtWriteVirtualMemory" to check who read and write memory of Application.
I have a question: Is there a way to check who read and write memory of Application in this application's process?
No. Not without hooking other processes/kernel (by hooking SSDT, as you've mentioned in your question). You can check which process has a handle to your application, but that doesn't necessarily mean that they've actually read/written anything.
To see which process has a handle to your process,
Call NtQuerySystemInformation with SystemHandleInformation(undocumented) for SystemInformationClass parameter, to enumerate all handles that are open on the system.
Duplicate all handles by calling DuplicateHandle with PROCESS_QUERY_INFORMATION access (if I recall correctly, this will filter out all non-process handles)
For each duplicated handle, call GetProcessId to get the process-id.
If the process-id matches with your application's process-id, then we can get the owner of the original handle by looking up the ProcessId field of the original SYSTEM_HANDLE_INFORMATION structure returned from NtQuerySystemInformation.

file_operations Question, how do i know if a process that opened a file for writing has decided to close it?

I'm currently writing a simple "multicaster" module.
Only one process can open a proc filesystem file for writing, and the rest can open it for reading.
To do so i use the inode_operation .permission callback, I check the operation and when i detect someone open a file for writing I set a flag ON.
i need a way to detect if a process that opened a file for writing has decided to close the file so i can set the flag OFF, so someone else can open for writing.
Currently in case someone is open for writing i save the current->pid of that process and when the .close callback is called I check if that process is the one I saved earlier.
Is there a better way to do that? Without saving the pid, perhaps checking the files that the current process has opened and it's permission...
Thanks!
No, it's not safe. Consider a few scenarios:
Process A opens the file for writing, and then fork()s, creating process B. Now both A and B have the file open for writing. When Process A closes it, you set the flag to 0 but process B still has it open for writing.
Process A has multiple threads. Thread X opens the file for writing, but Thread Y closes it. Now the flag is stuck at 1. (Remember that ->pid in kernel space is actually the userspace thread ID).
Rather than doing things at the inode level, you should be doing things in the .open and .release methods of your file_operations struct.
Your inode's private data should contain a struct file *current_writer;, initialised to NULL. In the file_operations.open method, if it's being opened for write then check the current_writer; if it's NULL, set it to the struct file * being opened, otherwise fail the open with EPERM. In the file_operations.release method, check if the struct file * being released is equal to the inode's current_writer - if so, set current_writer back to NULL.
PS: Bandan is also correct that you need locking, but the using the inode's existing i_mutex should suffice to protect the current_writer.
I hope I understood your question correctly: When someone wants to write to your proc file, you set a variable called flag to 1 and also save the current->pid in a global variable. Then, when any close() entry point is called, you check current->pid of the close() instance and compare that with your saved value. If that matches, you turn flag to off. Right ?
Consider this situation : Process A wants to write to your proc resource, and so you check the permission callback. You see that flag is 0, so you can set it to 1 for process A. But at that moment, the scheduler finds out process A has used up its time share and chooses a different process to run(flag is still o!). After sometime, process B comes up wanting to write to your proc resource also, checks that the flag is 0, sets it to 1, and then goes about writing to the file. Unfortunately at this moment, process A gets scheduled to run again and since, it thinks that flag is 0 (remember, before the scheduler pre-empted it, flag was 0) and so sets it to 1 and goes about writing to the file. End result : data in your proc resource goes corrupt.
You should use a good locking mechanism provided by the kernel for this type of operation and based on your requirement, I think RCU is the best : Have a look at RCU locking mechanism

Resources