Can I delete a named semaphore created with sem_open? - macos

I am experimenting with the named semaphores and there is something that I don't understand about the behavior of sem_close and sem_destroy. In my example, it looks like the semaphore that I create does not get deleted.
#include <iostream>
#include <semaphore.h>
int main() {
char sem_name[] = "/sem-1";
{
sem_t *sptr = sem_open(sem_name, O_CREAT, 0644, 0);
if (sptr != SEM_FAILED) {
printf("sem_open success\n");
// neither of these works
sem_close(sptr);
// sem_destroy(sptr);
} else {
printf("sem_open error #1: %s\n", strerror(errno));
}
}
sem_t *sptr = sem_open(sem_name, O_CREAT | O_EXCL, 0644, 0);
printf("sem_open error #2: %s\n", strerror(errno));
assert(sptr != SEM_FAILED);
return 0;
}
The output:
sem_open success
sem_open error #2: File exists
Assertion failed: (sptr != SEM_FAILED), function main, file /tmp/delete_me/main.cpp, line 22.
I would expect the assertion to not be hit and also the error #2 to not shown.
Additionally, macOS says that the sem_destroy method is deprecated but I am still using both sem_close() and sem_destroy but they both seem to not delete the semaphore.
Background: I am trying to port NASA Core Flight System to macOS. Their POSIX implementation uses sem_ calls and I am trying to understand if I can make them work on macOS with some minor modifications.

Since macOS only recognizes named semaphores, using sem_destroy() won't work. sem_destroy() destroys an unnamed semaphore at the address pointed to by sem. Only a semaphore that has been initialized by sem_init() should be
destroyed using sem_destroy().
You could likely overcome this issue by using sem_unlink:
...
sem_close(sptr);
sem_unlink(sem_name);
...
SEM_UNLINK(2)
NAME
sem_unlink -- remove a named semaphore
SYNOPSIS
#include <semaphore.h>
int sem_unlink(const char *name);
DESCRIPTION
The named semaphore named name is removed. If the semaphore is in use by
other processes, then name is immediately disassociated with the sema-phore, semaphore,
phore, but the semaphore itself will not be removed until all references
to it have been closed. Subsequent calls to sem_open() using name will
refer to or create a new semaphore named name.
If successful, `sem_unlink()` will return 0. Otherwise, -1 is returned and
errno is set, and the state of the semaphore is unchanged.
ERRORS
sem_unlink() succeeds unless:
[EACCES] Permission is denied to be remove the semaphore.
[ENAMETOOLONG] name exceeded SEM_NAME_LEN characters.
[ENOENT] The named semaphore does not exist.
↳ macOS Manual Pages | sem_unlink()

Related

Get address family from socket OS X

Getting address family can be done with getsockopt() with option SO_DOMAIN (see socket options) on linux.
(read Get address family from socket. Linux)
How do I do the same thing on OS X ?
When using the code that worked on linux on OS X I get
error: use of undeclared identifier 'SO_DOMAIN'
int err = getsockopt(sock, SOL_SOCKET, SO_DOMAIN, &addr_family, &len);
^
so not SO_DOMAIN ?
You can find this out by calling proc_pidfdinfo() on your own PID, and requesting PROC_PIDFDSOCKETINFO:
#include <libproc.h>
#include <stdbool.h>
#include <unistd.h>
bool socketDomainGet(int socket, int *domain) {
struct socket_fdinfo info;
int rc = proc_pidfdinfo(getpid(), socket, PROC_PIDFDSOCKETINFO, &info, sizeof info);
if (rc <= 0) return false;
*domain = info.psi.soi_family;
return true;
}
Unlike getsockname(), this works even if the socket hasn't been bound yet. Note as well as the domain (psi.soi_family), it also can tell you the type (psi.soi_type) and the protocol (psi.soi_protocol).
Keep in mind though this warning Apple gives in the libproc.h header:
/*
* This header file contains private interfaces to obtain process information.
* These interfaces are subject to change in future releases.
*/
They probably aren't going to break this, but the risk is higher than for more official APIs.
use SO_TYPE instead of SO_DOMAIN
in OS X man GETSOCKOPT(2) says
SO_TYPE get the type of the socket (get only)

How to send signal from kernel to user space

My kernel module code needs to send signal [def.] to a user land program, to transfer its execution to registered signal handler.
I know how to send signal between two user land processes, but I can not find any example online regarding the said task.
To be specific, my intended task might require an interface like below (once error != 1, code line int a=10 should not be executed):
void __init m_start(){
...
if(error){
send_signal_to_userland_process(SIGILL)
}
int a = 10;
...
}
module_init(m_start())
An example I used in the past to send signal to user space from hardware interrupt in kernel space. That was just as follows:
KERNEL SPACE
#include <asm/siginfo.h> //siginfo
#include <linux/rcupdate.h> //rcu_read_lock
#include <linux/sched.h> //find_task_by_pid_type
static int pid; // Stores application PID in user space
#define SIG_TEST 44
Some "includes" and definitions are needed. Basically, you need the PID of the application in user space.
struct siginfo info;
struct task_struct *t;
memset(&info, 0, sizeof(struct siginfo));
info.si_signo = SIG_TEST;
// This is bit of a trickery: SI_QUEUE is normally used by sigqueue from user space, and kernel space should use SI_KERNEL.
// But if SI_KERNEL is used the real_time data is not delivered to the user space signal handler function. */
info.si_code = SI_QUEUE;
// real time signals may have 32 bits of data.
info.si_int = 1234; // Any value you want to send
rcu_read_lock();
// find the task with that pid
t = pid_task(find_pid_ns(pid, &init_pid_ns), PIDTYPE_PID);
if (t != NULL) {
rcu_read_unlock();
if (send_sig_info(SIG_TEST, &info, t) < 0) // send signal
printk("send_sig_info error\n");
} else {
printk("pid_task error\n");
rcu_read_unlock();
//return -ENODEV;
}
The previous code prepare the signal structure and send it. Bear in mind that you need the application's PID. In my case the application from user space send its PID through ioctl driver procedure:
static long dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) {
ioctl_arg_t args;
switch (cmd) {
case IOCTL_SET_VARIABLES:
if (copy_from_user(&args, (ioctl_arg_t *)arg, sizeof(ioctl_arg_t))) return -EACCES;
pid = args.pid;
break;
USER SPACE
Define and implement the callback function:
#define SIG_TEST 44
void signalFunction(int n, siginfo_t *info, void *unused) {
printf("received value %d\n", info->si_int);
}
In main procedure:
int fd = open("/dev/YourModule", O_RDWR);
if (fd < 0) return -1;
args.pid = getpid();
ioctl(fd, IOCTL_SET_VARIABLES, &args); // send the our PID as argument
struct sigaction sig;
sig.sa_sigaction = signalFunction; // Callback function
sig.sa_flags = SA_SIGINFO;
sigaction(SIG_TEST, &sig, NULL);
I hope it helps, despite the fact the answer is a bit long, but it is easy to understand.
You can use, e.g., kill_pid(declared in <linux/sched.h>) for send signal to the specified process. To form parameters to it, see implementation of sys_kill (defined as SYSCALL_DEFINE2(kill) in kernel/signal.c).
Note, that it is almost useless to send signal from the kernel to the current process: kernel code should return before user-space program ever sees signal fired.
Your interface is violating the spirit of Linux. Don't do that..... A system call (in particular those related to your driver) should only fail with errno (see syscalls(2)...); consider eventfd(2) or netlink(7) for such asynchronous kernel <-> userland communications (and expect user code to be able to poll(2) them).
A kernel module could fail to be loaded. I'm not familiar with the details (never coded any kernel modules) but this hello2.c example suggests that the module init function can return a non zero error code on failure.
People are really expecting that signals (which is a difficult and painful concept) are behaving as documented in signal(7) and what you want to do does not fit in that picture. So a well behaved kernel module should never asynchronously send any signal to processes.
If your kernel module is not behaving nicely your users would be pissed off and won't use it.
If you want to fork your experimental kernel (e.g. for research purposes), don't expect it to be used a lot; only then could you realistically break signal behavior like you intend to do, and you could code things which don't fit into the kernel module picture (e.g. add a new syscall). See also kernelnewbies.

Find out the process name by pid in osx kernel extension

I am working on kernel extension and want to find out how to find process name by pid in kernel extension
This code works great in user space
static char procdata[4096];
int mib[3] = { CTL_KERN, KERN_PROCARGS, pid };
procdata[0] = '\0'; // clear
size_t size = sizeof(procdata);
if (sysctl(mib, 3, procdata, &size, NULL, 0)) {
return ERROR(ERROR_INTERNAL);
}
procdata[sizeof(procdata)-2] = ':';
procdata[sizeof(procdata)-1] = '\0';
ret = procdata;
return SUCCESS;
but for the kernel space, there are errors such as "Use of undeclared identifier 'CTL_KERN'" (even if I add #include )
What is the correct way to do it in kernel extension?
The Kernel.framework header <sys/proc.h> is what you're looking for.
In particular, you can use proc_name() to get a process's name given its PID:
/* this routine copies the process's name of the executable to the passed in buffer. It
* is always null terminated. The size of the buffer is to be passed in as well. This
* routine is to be used typically for debugging
*/
void proc_name(int pid, char * buf, int size);
Note however, that the name will be truncated to MAXCOMLEN - 16 bytes.
You might also be able to use the sysctl via sysctlbyname() from the kernel. In my experience, that function doesn't work well though, as the sysctl buffer memory handling isn't expecting buffers in kernel address space, so most types of sysctl will cause a kernel panic if called from a non-kernel thread. It also doesn't seem to work for all sysctls.

Problems doing syscall hooking

I use the following module code to hooks syscall, (code credited to someone else, e.g., Linux Kernel: System call hooking example).
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/unistd.h>
#include <asm/semaphore.h>
#include <asm/cacheflush.h>
void **sys_call_table;
asmlinkage int (*original_call) (const char*, int, int);
asmlinkage int our_sys_open(const char* file, int flags, int mode)
{
printk(KERN_ALERT "A file was opened\n");
return original_call(file, flags, mode);
}
int set_page_rw(long unsigned int _addr)
{
struct page *pg;
pgprot_t prot;
pg = virt_to_page(_addr);
prot.pgprot = VM_READ | VM_WRITE;
return change_page_attr(pg, 1, prot);
}
int init_module()
{
// sys_call_table address in System.map
sys_call_table = (void*)0xffffffff804a1ba0;
original_call = sys_call_table[1024];
set_page_rw(sys_call_table);
sys_call_table[1024] = our_sys_open;
return 0;
}
void cleanup_module()
{
// Restore the original call
sys_call_table[1024] = original_call;
}
When insmod the compiled .ko file, terminal throws "Killed". When looking into 'cat /proc/modules' file, I get the Loading status.
my_module 10512 1 - Loading 0xffffffff882e7000 (P)
As expected, I can not rmmod this module, as it complains its in use. The system is rebooted to get a clean-slate status.
Later on, after commenting two code lines in the above source sys_call_table[1024] = our_sys_open; and sys_call_table[1024] = original_call;, it can insmod successfully. More interestingly, when uncommenting these two lines (change back to the original code), the compiled module can be insmod successfully. I dont quite understand why this happens? And is there any way to successfully compile the code and insmod it directly?
I did all this on Redhat with linux kernel 2.6.24.6.
I think you should take a look to the kprobes API, which is well documented in Documentation/krpobes.txt. It gives you the ability to install handler on every address (e.g. syscall entry) so that you can do what you want. Added bonus is that your code would be more portable.
If you're only interested in tracing those syscalls you can use the audit subsystem, coding your own userland daemon which will be able to receive events on a NETLINK socket from the audit kthread. libaudit provides a simple API to register/read events.
If you do have a good reason with not using kprobes/audit, I would suggest that you check that the value you are trying to write to is not above the page that you set writable. A quick calculation shows that:
offset_in_sys_call_table * sizeof(*sys_call_table) = 1024 * 8 = 8192
which is two pages after the one you set writable if you are using 4K pages.

scoped_lock doesn't work on file?

According to the link below, I wrote a small test case. But it doesn't work. Any idea is appreciated!
Reference:
http://www.cppprog.com/boost_doc/doc/html/interprocess/synchronization_mechanisms.html#interprocess.synchronization_mechanisms.file_lock.file_lock_careful_iostream
#include <iostream>
#include <fstream>
#include <boost/interprocess/sync/file_lock.hpp>
#include <boost/interprocess/sync/scoped_lock.hpp>
using namespace std;
using namespace boost::interprocess;
int main()
{
ofstream file_out("fileLock.txt");
file_lock f_lock("fileLock.txt");
{
scoped_lock<file_lock> e_lock(f_lock); // it works if I comment this out
file_out << 10;
file_out.flush();
file_out.close();
}
return 0;
}
Running the test on Linux produces your desired output. I notice these two warnings:
The page you reference has this warning: "If you are using a std::fstream/native file handle to write to the file while using file locks on that file, don't close the file before releasing all the locks of the file."
Boost::file_lock apparently uses LockFileEx on Windows. MSDN has this to say: "If the locking process opens the file a second time, it cannot access the specified region through this second handle until it unlocks the region."
It seems like, on Windows at least, the file lock is per-handle, not per-file. As near as I can tell, that means that your program is guaranteed to fail under Windows.
Your code appears to be susceptible to this long-standing bug on the boost trac site: https://svn.boost.org/trac/boost/ticket/2796
The title of that bug is "interprocess::file_lock has incorrect behavior when win32 api is enabled".
Here is a workaround to append in a file with a file locking based on Boost 1.44.
#include "boost/format.hpp"
#include "boost/interprocess/detail/os_file_functions.hpp"
namespace ip = boost::interprocess;
namespace ipc = boost::interprocess::detail;
void fileLocking_withHandle()
{
static const string filename = "fileLocking_withHandle.txt";
// Get file handle
boost::interprocess::file_handle_t pFile = ipc::create_or_open_file(filename.c_str(), ip::read_write);
if ((pFile == 0 || pFile == ipc::invalid_file()))
{
throw runtime_error(boost::str(boost::format("File Writer fail to open output file: %1%") % filename).c_str());
}
// Lock file
ipc::acquire_file_lock(pFile);
// Move writing pointer to the end of the file
ipc::set_file_pointer(pFile, 0, ip::file_end);
// Write in file
ipc::write_file(pFile, (const void*)("bla"), 3);
// Unlock file
ipc::release_file_lock(pFile);
// Close file
ipc::close_file(pFile);
}

Resources