storage size of isn’t known using sigaltstack struct - c

I'm using the sigalstack struct, details at:
Here (MAC OSX)
HERE (LINUX)
I'm just declaring it like so
struct sigaltstack aa;
and i keep getting the following error
error: storage size of ‘aa’ isn’t known
I read and checked storage size of ‘names’ isn’t known but I'm just declaring it, so it doesn't really apply.

You can't just use an uninitialized alternate stack like that. You have to allocate the space for the stack in its ss_sp field and set the corresponding size in its ss_size field.
The man7 link you linked has more information on this. In fact, it provides an example at the bottom of the page:
stack_t ss;
ss.ss_sp = malloc(SIGSTKSZ);
if (ss.ss_sp == NULL)
/* Handle error */;
ss.ss_size = SIGSTKSZ;
ss.ss_flags = 0;
if (sigaltstack(&ss, NULL) == -1)
/* Handle error */;
Hope that helps.

The Mac OS page you link to says (in the section on 'Legacy Synopsis'):
COMPATIBILITY
Use of the (obsolete) sigaltstack struct will cause compiler diagnostics. Use stack_t, defined in <signal.h>.
This suggests that you should not attempt to use struct sigaltstack. The page also shows how you're expected to do it on Mac OS. The Linux page also shows how you're supposed to use the stack_t type and makes no mention of struct sigaltstack at all.

Related

Why calling `free(malloc(8))`?

The Objective-C runtime's hashtable2.mm file contains the following code:
static void bootstrap (void) {
free(malloc(8));
prototypes = ALLOCTABLE (DEFAULT_ZONE);
prototypes->prototype = &protoPrototype;
prototypes->count = 1;
prototypes->nbBuckets = 1; /* has to be 1 so that the right bucket is 0 */
prototypes->buckets = ALLOCBUCKETS(DEFAULT_ZONE, 1);
prototypes->info = NULL;
((HashBucket *) prototypes->buckets)[0].count = 1;
((HashBucket *) prototypes->buckets)[0].elements.one = &protoPrototype;
};
Why does it allocate and release the 8-bytes space immediately?
Another source of confusion is this method from objc-os.h:
static __inline void *malloc_zone_malloc(malloc_zone_t z, size_t size) { return malloc(size); }
While it uses only one parameter, does the signature ask for two?
For the first question I can only assume. My bet it was done to avoid/reduce memory churn, or segment the memory for some other reason. You can briefly find where it's discussed in the Changelog of bmalloc (which is not quite relevant, but i could not find a better reference):
2017-06-02 Geoffrey Garen <ggaren#apple.com>
...
Updated for new APIs. Note that we cache one free chunk per page
class. This avoids churn in the large allocator when you
free(malloc(X))
It's unclear however, if the memory churn is caused by this technique or it was supposed to address it.
For the second question, Objective-C runtime used to work with "zones" in order to destroy all allocated variables by just destroying the said zone, but it proved being error prone and later it was agreed to not use it anymore. The API, however still uses it for historical reasons (backward compatibility, i assume), but says that zones are ignored:
Zones are ignored on iOS and 64-bit runtime on OS X. You should not use zones in current development.

vm_start is not the same as from /proc/pid/maps

I am currently studying Linux internals and I am confused about the address pointed by vm_start. My goal is to retrieve a loaded .so/module base address from within the kernel. Here is what I got:
// loop through task' memory maps
for (struct vm_area_struct *i = task->mm->mmap; NULL != i; i = i->vm_next)
{
if (NULL == i->vm_file)
{
continue;
}
// if the module name matches
if (string_ends_with (i->vm_file->f_path.dentry->d_iname, module_name))
{
return i->vm_start; // return mapping start
}
}
return NULL; // the specified module is not loaded in memory
This code returned the address f7888000, however, by checking this in /proc/pid/maps the correct address is 7f0ef7888000 (which I expected to be returned from my function). I find this odd, since show_vma_header_prefix itself is called with vm_start as a parameter, as we can see here: https://github.com/torvalds/linux/blob/master/fs/proc/task_mmu.c#L968.
Am I mistaking something? Why is the address returned from my function 7f0e00000000 bytes away from the expected result? Is there a way I can get this value from kernel space? Reading from /proc/pid/maps is out of question and the target process is not mine, I want to retrieve the address externally. This is not production code, I know reading from proc/maps and then passing as a argument is definitely a better way. However, this is a experimental rootkit for studying purposes.
TL;DR vm_start is 7f0e00000000 bytes off from the expected result

libnl 'invalid argument (-22) while trying using nl80211

I tried to extend the 'iw' utility to allow it to set the maximum and minimum size of the 802.11 contention window. But I'm always getting a 'invalid argument (-22)' returned.
I edited phy.c of the iw-3.15 source and appended
static int handle_txq(struct nl80211_state *state,
struct nl_cb *cb,
struct nl_msg *msg,
int argc, char **argv,
enum id_input id)
{
unsigned int cw_min, cw_max;
printf("HANDLE TXQ");
if (argc != 2)
return 1;
cw_min = atoi(argv[0]);
cw_max = atoi(argv[1]);
printf("setting contention window to: %d - %d\n",cw_min,cw_max);
//create nested txq array
struct nlattr *nested;
nested = nla_nest_start(msg,NL80211_ATTR_WIPHY_TXQ_PARAMS);
NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMIN,cw_min);
NLA_PUT_U16(msg,NL80211_TXQ_ATTR_CWMAX,cw_max);
nla_nest_end(msg,nested);
return 0;
nla_put_failure:
return -ENOBUFS;
}
COMMAND(set, txq, "<cw_min> <cw_max>",
NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txq,
"Set contention window minimum and maximum size.\n"
"Valid values: 1 - 32767 in the form 2^n-1");
COMMAND(set, txq, "<cw_min> <cw_max>",
NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txq,
"Set contention window minimum and maximum size.\n"
"Valid values: 1 - 32767 in the form 2^n-1");
I couldn't find any good documentation of nl80211 or it's usage through netlink except the header file itself. I am not
sure if I contruct the nested message according to specification and using U16 for the attributes are an educated guess (they are uint_16 in the matching cfg80211).
From my understanding of netlink my message assembly should be correct, but since I get an error I'm probably wrong...
Does anyone have a good documentation for nl80211 and its usage? Can anyone spot my problem?
From the kernel code on the other end of the netlink socket (in linux/net/wireless/nl80211.c - I am using 3.13.0-30), it seems there are a few reasons you can get an "invalid argument" (-EINVAL) response.
Firstly, you need to give it a valid interface and the device needs to be in AP or P2P_GO mode. You also need to provide all the TXQ params, not just contention window values. See the nl80211_set_wiphy() and parse_txq_params() functions in nl80211.c if you want to see exactly how your message is being handled.
You do appear to be using the correct types for the parameters though: NL80211_TXQ_ATTR_QUEUE/NL80211_TXQ_ATTR_AC (depending on version) and NL80211_TXQ_ATTR_AIFS are u8, and the other three (NL80211_TXQ_ATTR_TXOP, NL80211_TXQ_ATTR_CWMIN and NL80211_TXQ_ATTR_CWMAX) are u16.

keyboard interrupt handler giving null value

I am learning Linux Kernel Module programming(Interrupt Handler) and using the tutorial (http://tldp.org/LDP/lkmpg/2.6/html/) exact module link(http://tldp.org/LDP/lkmpg/2.6/html/x1256.html).
In the tutorial I am getting error when I used
INIT_WORK(&task, got_char, &scancode);
The error was "error: macro "INIT_WORK" passed 3 arguments, but takes just 2"
So I found one solution and use the below line
INIT_WORK(&task, got_char);
It's working fine but the output I am getting is null. I am expecting the key number from the keyboard.
Any body have any idea ?
If it is not clear please let me know I will try to interpret more.
Thanks
Add a structure like follows,
struct getchar_info {
/* Other info ... */
struct work_struct work;
unsigned int scancode;
/* Other info ... */
};
static struct getchar_info gci; /* Statically declare or use kmalloc() */
Change got_char() to,
static void got_char(struct work_struct *work)
{
struct getchar_info *info = container_of(work, struct getchar_info, work);
info->scancode = my_val;
/* ... */
Initialize it like INIT_WORK(&gci.work, got_char);
This is a common Linux kernel paradigm or design pattern. The work queue code needs to manage this structure pointer so it is easy to provide to your got_char routine. Your driver must allocate it as part of a larger structure (it is inheritence in OO terms; it looks like composition as 'C' only supports that). The container_of is like a C++ dynamic_cast<> (with single inheritance in case any C++ gurus are looking). It lets you get the composed structure from the sub-structure.

How do I create a "netlink" between kernel and userspace?

I want to use netlink to communicate between an application and kernel space. My Linux kernel version is 2.6.28, and the following is my wrong code:
nf_sock=netlink_kernel_create(NL_PROTO,0,nl_user_skb,THIS_MODULE);
The abbreviated error message is:
error: too few arguments to function 'netlink_kernel_create'
In the file <linux/netlink.h>, the function netlink_kernel_create() is defined as
extern struct sock *netlink_kernel_create(struct net *net,int unit,unsigned int groups,void (*input)(struct sk_buff *skb),struct mutex *cb_mutex,struct module *module)
I don't understand what to use for the first argument, net. Can someone explain what I should use here?
A struct net contains information about the network namespace, a set of network resources available to processes. Note that there could be multiple network namespaces (i.e. multiple instances of the networking stack), but most drivers use the init_net namespace.
Your call should probably look something like the following
nf_sock = netlink_kernel_create(&init_net,
NETLINK_USERSOCK,
0,
nl_rcv_func,
NULL,
THIS_MODULE);
where nl_rcv_func is a function taking struct sk_buff *skb as the only argument and processes the received netlink message.
You seem to have been following a guide such as this one, which (being from 2005) might well have been outpaced by the development of the kernel. It seems the internal API to create a netlink from the kernel side has changed.
Either check the Documentation/ folder in your local kernel tree for some (hopefully fresher) documentation, or read the code itself. You could also trawl the Linux Kernel mailing list archives for any mention of the changes that seem to have happened.
Here is the actual implemntation as of 2.6.29, if you'd rather puzzle it out backwards (and haven't already checked this in your own tree, of course).
Yes, struct net is indeed for net namespace, but it is not proper to always use init_net, you should register your own pernet_operations, like this:
static struct pernet_operations fib_net_ops = {
.init = fib_net_init,
.exit = fib_net_exit,
};
static int __net_init fib_net_init(struct net *net)
{
int error;
#ifdef CONFIG_IP_ROUTE_CLASSID
net->ipv4.fib_num_tclassid_users = 0;
#endif
error = ip_fib_net_init(net);
if (error < 0)
goto out;
error = nl_fib_lookup_init(net);
if (error < 0)
goto out_nlfl;
error = fib_proc_init(net);
if (error < 0)
goto out_proc;
out:
return error;
out_proc:
nl_fib_lookup_exit(net);
out_nlfl:
ip_fib_net_exit(net);
goto out;
}
static int __net_init nl_fib_lookup_init(struct net *net)
{
struct sock *sk;
struct netlink_kernel_cfg cfg = {
.input = nl_fib_input,
};
sk = netlink_kernel_create(net, NETLINK_FIB_LOOKUP, &cfg);
if (sk == NULL)
return -EAFNOSUPPORT;
net->ipv4.fibnl = sk;
return 0;
}
and finally:
register_pernet_subsys(&fib_net_ops);
I would suggest ioctl for kernel/user communication. The ioctl interface is standard and the chance of been updated between kernels is small.

Resources